Files
seedpgp-web/src/components/QrDisplay.tsx

123 lines
4.2 KiB
TypeScript

import { useEffect, useState } from 'react';
import { Download } from 'lucide-react';
import QRCode from 'qrcode';
interface QrDisplayProps {
value: string | Uint8Array;
}
export const QrDisplay: React.FC<QrDisplayProps> = ({ value }) => {
const [dataUrl, setDataUrl] = useState('');
const [debugInfo, setDebugInfo] = useState('');
useEffect(() => {
if (!value) {
setDataUrl('');
return;
}
const generateQR = async () => {
try {
if (import.meta.env.DEV) {
console.debug('QR generation started', {
type: value instanceof Uint8Array ? 'Uint8Array' : typeof value,
length: value instanceof Uint8Array || typeof value === 'string' ? value.length : 0
});
}
if (value instanceof Uint8Array) {
// Create canvas manually for precise control
const canvas = document.createElement('canvas');
// Use the toCanvas method with Uint8Array directly
await QRCode.toCanvas(canvas, [{
data: value,
mode: 'byte'
}], {
errorCorrectionLevel: 'L',
width: 512,
margin: 4,
color: {
dark: '#000000',
light: '#FFFFFF'
}
});
const url = canvas.toDataURL('image/png');
setDataUrl(url);
setDebugInfo(`Binary QR: ${value.length} bytes`);
} else {
// For string data
console.log(' - String data:', value.slice(0, 50));
const url = await QRCode.toDataURL(value, {
errorCorrectionLevel: 'L',
type: 'image/png',
width: 512,
margin: 4,
color: {
dark: '#000000',
light: '#FFFFFF'
}
});
setDataUrl(url);
setDebugInfo(`String QR: ${value.length} chars`);
}
} catch (err) {
if (import.meta.env.DEV) {
console.error('QR generation error:', err);
}
setDebugInfo(`Error generating QR code`);
}
};
generateQR();
}, [value]);
const handleDownload = () => {
if (!dataUrl) return;
const now = new Date();
const date = now.toISOString().split('T')[0];
const time = now.toTimeString().split(' ')[0].replace(/:/g, '');
const filename = `SeedPGP_${date}_${time}.png`;
const link = document.createElement('a');
link.href = dataUrl;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
if (!dataUrl) return null;
return (
<div className="border-4 border-[#00f0ff] rounded-xl shadow-[0_0_40px_rgba(0,240,255,0.6)] p-4 bg-[#0a0a0f] space-y-4">
<div className="bg-[#16213e] p-6 rounded-lg inline-block shadow-[0_0_20px_rgba(0,240,255,0.3)] border-2 border-[#00f0ff]/30">
<img src={dataUrl} alt="QR Code" className="w-full h-auto" />
</div>
{debugInfo && (
<div className="text-xs text-[#6ef3f7] font-mono">
{debugInfo}
</div>
)}
<button
onClick={handleDownload}
className="flex items-center gap-2 px-4 py-2 bg-[#00f0ff] hover:bg-[#00f0ff]/80 text-[#0a0a0f] rounded-lg transition-all hover:shadow-[0_0_15px_rgba(0,240,255,0.5)]"
>
<Download size={16} />
Download QR Code
</button>
<p className="text-xs text-[#6ef3f7]">
Downloads as: SeedPGP_{new Date().toISOString().split('T')[0]}_HHMMSS.png
</p>
</div>
);
};