/** * @license * SPDX-License-Identifier: Apache-2.0 */ /* tslint:disable */ // FIX: Import `PersonGeneration` and `SafetyFilterLevel` enums from `@google/genai` to fix type errors. import { GoogleGenAI, PersonGeneration, SafetyFilterLevel, } from '@google/genai'; import JSZip from 'jszip'; import { Archive, Download, ImageIcon, LoaderCircle, SendHorizontal, SlidersHorizontal, Trash2, X, } from 'lucide-react'; import {useState} from 'react'; const ai = new GoogleGenAI({apiKey: process.env.API_KEY}); function parseError(error: string): React.ReactNode { if (error.includes('429') && error.includes('RESOURCE_EXHAUSTED')) { return ( <> You've exceeded your current API quota (Rate Limit). This is a usage limit on Google's servers.

Please check your plan and billing details, or try again after some time. For more information, visit the{' '} Gemini API rate limits documentation . ); } const regex = /"message":\s*"(.*?)"/g; const match = regex.exec(error); if (match && match[1]) { return match[1]; } return error; } export default function Home() { const [prompt, setPrompt] = useState(''); const [generatedImages, setGeneratedImages] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isZipping, setIsZipping] = useState(false); const [showErrorModal, setShowErrorModal] = useState(false); const [errorMessage, setErrorMessage] = useState(''); const [numberOfImages, setNumberOfImages] = useState(2); const [aspectRatio, setAspectRatio] = useState('1:1'); const [showSettings, setShowSettings] = useState(false); // New state for advanced settings const [model, setModel] = useState('imagen-4.0-fast-generate-001'); // FIX: Use the PersonGeneration enum for the personGeneration state to fix type errors. const [personGeneration, setPersonGeneration] = useState( PersonGeneration.ALLOW_ALL, ); const handleClear = () => { setGeneratedImages([]); setPrompt(''); setNumberOfImages(2); setAspectRatio('1:1'); setModel('imagen-4.0-fast-generate-001'); // FIX: Use enum members to set state, resolving type errors. setPersonGeneration(PersonGeneration.ALLOW_ALL); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!prompt) { setErrorMessage('Please enter a prompt to generate an image.'); setShowErrorModal(true); return; } setIsLoading(true); setGeneratedImages([]); // Clear previous results try { const response = await ai.models.generateImages({ model, prompt, config: { numberOfImages: Number(numberOfImages), aspectRatio, personGeneration, }, }); const imageUrls = response.generatedImages.map( (img) => `data:image/png;base64,${img.image.imageBytes}`, ); setGeneratedImages(imageUrls); } catch (error) { console.error('Error generating images:', error); const rawMessage = (error as Error).message || 'An unexpected error occurred.'; setErrorMessage(parseError(rawMessage)); setShowErrorModal(true); } finally { setIsLoading(false); } }; const handleDownload = (src: string, index: number) => { const link = document.createElement('a'); link.href = src; link.download = `imagen4-studio-${index + 1}.png`; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; const handleDownloadAll = async () => { if (generatedImages.length === 0) return; setIsZipping(true); try { const zip = new JSZip(); for (let i = 0; i < generatedImages.length; i++) { const src = generatedImages[i]; const base64Data = src.split(',')[1]; zip.file(`imagen4-studio-${i + 1}.png`, base64Data, {base64: true}); } const content = await zip.generateAsync({type: 'blob'}); const link = document.createElement('a'); link.href = URL.createObjectURL(content); link.download = 'imagen4-studio-images.zip'; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(link.href); } catch (error) { console.error('Error creating zip file:', error); setErrorMessage('Failed to create the zip file.'); setShowErrorModal(true); } finally { setIsZipping(false); } }; const closeErrorModal = () => { setShowErrorModal(false); }; const models = [ {id: 'imagen-4.0-fast-generate-001', name: 'Imagen 4 Fast'}, {id: 'imagen-4.0-generate-001', name: 'Imagen 4'}, {id: 'imagen-4.0-ultra-generate-001', name: 'Imagen 4 Ultra'}, ]; // FIX: Use enum members for option IDs to ensure type safety. const personGenerationOptions = [ {id: PersonGeneration.ALLOW_ALL, name: 'Allow All'}, {id: PersonGeneration.ALLOW_ADULT, name: 'Allow Adults'}, {id: PersonGeneration.DONT_ALLOW, name: "Don't Allow"}, ]; const aspectRatios = ['1:1', '16:9', '4:3', '3:4', '9:16']; const SettingButton = ({onClick, current, value, children}) => ( ); return ( <>

IMAGEN4 AIO

Powered by the{' '} Google Gemini API

0 ? 'items-start' : 'items-center' }`}> {isLoading ? (

Generating images...

This may take a moment

) : generatedImages.length > 0 ? (
1 ? 'grid-cols-1 sm:grid-cols-2' : 'grid-cols-1' }`}> {generatedImages.map((src, index) => (
{`Generated
))}
) : (

Your generated images will appear here

Enter a prompt below to get started

)}
{/* Input form */}
setPrompt(e.target.value)} placeholder="Describe the image you want to create..." className="w-full p-3 sm:p-4 pr-12 sm:pr-14 text-sm sm:text-base border-2 border-black bg-white text-gray-800 shadow-sm focus:ring-2 focus:ring-gray-200 focus:outline-none transition-all h-14" required />
{/* Settings Modal */} {showSettings && (
setShowSettings(false)}>
e.stopPropagation()}>

Settings

Model
{models.map((m) => ( {m.name} ))}
Person Generation
{personGenerationOptions.map((opt) => ( {opt.name} ))}
{ const val = Math.max( 1, Math.min(4, Number(e.target.value)), ); setNumberOfImages(val); }} className="w-24 p-2 border border-gray-300 rounded-md shadow-sm focus:ring-gray-500 focus:border-gray-500" />
Aspect Ratio
{aspectRatios.map((ratio) => ( {ratio} ))}
)} {/* Error Modal */} {showErrorModal && (

Generation Failed

{errorMessage}
)}
); }