import React, { useState, useCallback } from 'react'; import { UploadedImage, AppStep, GenerationResult } from './types'; import { expandPrompt, generateImage, refineImage } from './services/geminiService'; import ImageUploader from './components/ImageUploader'; import ImageSegmenter from './components/ImageSegmenter'; import PromptCustomizer from './components/PromptCustomizer'; import ImageResult from './components/ImageResult'; import StepIndicator from './components/StepIndicator'; import { SparklesIcon } from './components/icons/SparklesIcon'; import { applyMask } from './utils/canvasUtils'; import { LoggingProvider, useLogger } from './contexts/LoggingContext'; import DebugConsole from './components/DebugConsole'; const AppContent: React.FC = () => { const [step, setStep] = useState(AppStep.Upload); const [uploadedImages, setUploadedImages] = useState([]); const [masterPrompt, setMasterPrompt] = useState(''); const [generationResult, setGenerationResult] = useState(null); const [isLoading, setIsLoading] = useState(false); const [loadingMessage, setLoadingMessage] = useState(''); const [error, setError] = useState(null); const { log } = useLogger(); const handleImagesUploaded = (images: UploadedImage[]) => { log('info', `${images.length} images uploaded. Moving to segmentation step.`); setUploadedImages(images); setStep(AppStep.Segment); setError(null); }; const handleSegmentationComplete = (imagesWithMasks: UploadedImage[]) => { log('success', `Segmentation complete for all ${imagesWithMasks.length} images. Moving to prompt step.`); setUploadedImages(imagesWithMasks); setStep(AppStep.Prompt); setError(null); }; const handlePromptExpanded = useCallback(async (scenario: string, userInstruction: string) => { setIsLoading(true); setLoadingMessage('Expanding your idea into a master prompt...'); setError(null); log('info', `Expanding prompt with scenario: "${scenario}"`); try { const prompt = await expandPrompt(scenario, userInstruction, uploadedImages); setMasterPrompt(prompt); log('success', 'Master prompt created successfully.'); } catch (e) { const errorMessage = e instanceof Error ? e.message : 'An unknown error occurred during prompt expansion.'; log('error', `Prompt expansion failed: ${errorMessage}`); setError(errorMessage); } finally { setIsLoading(false); setLoadingMessage(''); } }, [uploadedImages, log]); const handleFinalGeneration = useCallback(async (finalPrompt: string) => { setIsLoading(true); setLoadingMessage('Generating your K-Pop thumbnail...'); setError(null); log('info', 'Starting final image generation.'); try { log('info', 'Applying masks to create segmented images...'); const segmentedImages = await Promise.all( uploadedImages.map(async (image) => { if (!image.maskDataUrl) { throw new Error(`Mask is missing for image: ${image.file.name}`); } const segmentedData = await applyMask(image.previewUrl, image.maskDataUrl); return { ...image, segmentedDataUrl: `data:image/png;base64,${segmentedData}` }; }) ); log('success', 'Masks applied successfully.'); const result = await generateImage(finalPrompt, segmentedImages); setGenerationResult({ baseImage: result, currentImage: result, history: [result], }); setStep(AppStep.Result); log('success', 'Thumbnail generated successfully.'); } catch (e) { const errorMessage = e instanceof Error ? e.message : 'An unknown error occurred during image generation.'; log('error', `Final image generation failed: ${errorMessage}`); setError(errorMessage); setStep(AppStep.Prompt); } finally { setIsLoading(false); setLoadingMessage(''); } }, [uploadedImages, log]); const handleImageRefinement = useCallback(async (refinementPrompt: string) => { if (!generationResult) return; setIsLoading(true); setLoadingMessage('Applying your refinements...'); setError(null); log('info', `Refining image with prompt: "${refinementPrompt}"`); try { const newImage = await refineImage(refinementPrompt, generationResult.currentImage); setGenerationResult(prev => { if (!prev) return null; const newHistory = [...prev.history, newImage]; return { baseImage: prev.baseImage, currentImage: newImage, history: newHistory, }; }); log('success', 'Image refined successfully.'); } catch (e) { const errorMessage = e instanceof Error ? e.message : 'An unknown error occurred during image refinement.'; log('error', `Image refinement failed: ${errorMessage}`); setError(errorMessage); } finally { setIsLoading(false); setLoadingMessage(''); } }, [generationResult, log]); const handleBack = () => { setError(null); if (step === AppStep.Result) { log('info', 'Navigating back from Result to Prompt step.'); setMasterPrompt(''); setStep(AppStep.Prompt); } else if (step === AppStep.Prompt) { log('info', 'Navigating back from Prompt to Segment step.'); setMasterPrompt(''); setStep(AppStep.Segment); } else if (step === AppStep.Segment) { log('info', 'Navigating back from Segment to Upload step.'); setStep(AppStep.Upload); } }; const handleStartOver = () => { log('info', 'Starting over. Resetting application state.'); setStep(AppStep.Upload); setUploadedImages([]); setMasterPrompt(''); setGenerationResult(null); setIsLoading(false); setLoadingMessage(''); setError(null); } const renderStep = () => { switch (step) { case AppStep.Upload: return ; case AppStep.Segment: return ; case AppStep.Prompt: return ; case AppStep.Result: return ; default: return ; } }; return (

K-Pop Thumbnail Genie

Create stunning, emotional YouTube thumbnails with the magic of AI

{error && (

Error: {error}

)} {renderStep()}

Powered by Google Gemini. Designed for K-Pop content creators.

); }; const App: React.FC = () => ( ); export default App;