import React, { useState, useRef, useCallback } from 'react'; import { Button } from '../ui/Button'; import { Input } from '../ui/input'; import { Label } from '../ui/label'; import Typography from '../ui/Typography'; import { Alert, AlertDescription, AlertTitle } from '../ui/alert'; import { Upload, X, Image as ImageIcon, FileWarning } from 'lucide-react'; import { cn } from '../../lib/utils'; interface InscriptionSelectProps { onChange: (hcsUrl: string) => void; formData?: string | null; introMessage: string; warningMessage: string; network: string; messageEnabled: boolean; uploadMessage?: string; } /** * InscriptionSelect component for selecting HCS-11 inscribed files * Simplified version for the conversational agent app */ export function InscriptionSelect({ onChange, formData, introMessage, warningMessage, network = 'testnet', messageEnabled = true, uploadMessage, }: InscriptionSelectProps) { const [manualTopicId, setManualTopicId] = useState(''); const [selectedFile, setSelectedFile] = useState(null); const [isUploading, setIsUploading] = useState(false); const [uploadError, setUploadError] = useState(null); const fileInputRef = useRef(null); const MAX_FILE_SIZE = 5 * 1024 * 1024; const ACCEPTED_FORMATS = { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg'], 'image/gif': ['.gif'], 'image/webp': ['.webp'], }; /** * Handle manual topic ID submission */ const handleManualTopicIdSubmit = useCallback(() => { if (manualTopicId.trim()) { const formattedUrl = manualTopicId.startsWith('hcs://') ? manualTopicId : `hcs://${manualTopicId}`; onChange(formattedUrl); setManualTopicId(''); } }, [manualTopicId, onChange]); /** * Handle file selection for upload */ const handleFileSelect = useCallback( async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; setUploadError(null); if (file.size > MAX_FILE_SIZE) { setUploadError('Image size must be less than 5MB'); return; } if (!Object.keys(ACCEPTED_FORMATS).includes(file.type)) { setUploadError( 'Please select a valid image file (PNG, JPG, GIF, or WebP)' ); return; } setSelectedFile(file); setIsUploading(true); const reader = new FileReader(); reader.onload = (e) => { const dataUrl = e.target?.result as string; if (!dataUrl) { setUploadError('Failed to read file data'); setIsUploading(false); return; } onChange(dataUrl); setIsUploading(false); setUploadError(null); }; reader.onerror = () => { setUploadError('Failed to read file'); setIsUploading(false); }; reader.readAsDataURL(file); }, [] ); /** * Handle inscribe button click */ const handleInscribeClick = useCallback(() => { fileInputRef.current?.click(); }, []); /** * Handle file deletion */ const handleDeleteFile = useCallback(() => { onChange(''); setSelectedFile(null); setUploadError(null); }, [onChange]); const isExistingPfp = formData && formData.startsWith('hcs://'); const isDataUrl = formData && formData.startsWith('data:'); const pfpTopicId = isExistingPfp ? formData.replace('hcs://', '') : null; return (
{introMessage}
setManualTopicId(e.target.value)} className='w-full' />
{!formData && messageEnabled && ( No File Selected {warningMessage} )} {uploadError && ( Upload Error {uploadError} )} {formData && formData !== '' ? (
{isDataUrl ? ( <> Profile { const target = e.target as HTMLImageElement; target.style.display = 'none'; target.parentElement?.classList.add( 'bg-muted', 'flex', 'items-center', 'justify-center' ); if (target.parentElement) { target.parentElement.innerHTML = '
Failed to load image
'; } }} />
{isUploading && (
Processing...
)}
) : pfpTopicId ? ( Profile { const target = e.target as HTMLImageElement; target.style.display = 'none'; target.parentElement?.classList.add( 'bg-muted', 'flex', 'items-center', 'justify-center' ); if (target.parentElement) { target.parentElement.innerHTML = '
Image not found
'; } }} /> ) : (
)}
{selectedFile ? `Selected: ${selectedFile.name} (${( selectedFile.size / 1024 ).toFixed(1)}KB)` : isDataUrl ? 'New image (will be inscribed on registration)' : `Topic: ${pfpTopicId || 'Unknown'}`}
) : null}
); }