Spaces:
Running
Running
| // AI Generation Manager | |
| class AIGenerationManager { | |
| constructor() { | |
| if (!localStorage.getItem('generationHistory')) { | |
| localStorage.setItem('generationHistory', JSON.stringify([])); | |
| } | |
| this.favoriteGenerations = JSON.parse(localStorage.getItem('favoriteGenerations') || '[]'); | |
| } | |
| saveGeneration(prompt, images, metadata = {}) { | |
| const history = JSON.parse(localStorage.getItem('generationHistory')); | |
| history.unshift({ | |
| prompt, | |
| images, | |
| metadata: { | |
| model: metadata.model || 'stable-diffusion-v2', | |
| style: metadata.style || 'default', | |
| timestamp: new Date().toISOString(), | |
| favorite: false | |
| } | |
| }); | |
| localStorage.setItem('generationHistory', JSON.stringify(history)); | |
| } | |
| addFeedback(id, feedback) { | |
| const history = JSON.parse(localStorage.getItem('generationHistory')); | |
| const item = history.find(item => item.id === id); | |
| if (item) { | |
| item.feedback = feedback; | |
| localStorage.setItem('generationHistory', JSON.stringify(history)); | |
| } | |
| } | |
| toggleFavorite(id) { | |
| const history = JSON.parse(localStorage.getItem('generationHistory')); | |
| const item = history.find(item => item.id === id); | |
| if (item) { | |
| item.metadata.favorite = !item.metadata.favorite; | |
| localStorage.setItem('generationHistory', JSON.stringify(history)); | |
| return item.metadata.favorite; | |
| } | |
| return false; | |
| } | |
| getHistory() { | |
| return JSON.parse(localStorage.getItem('generationHistory')); | |
| } | |
| getFavorites() { | |
| return this.getHistory().filter(item => item.metadata.favorite); | |
| } | |
| } | |
| const aiManager = new AIGenerationManager(); | |
| document.addEventListener('DOMContentLoaded', async function() { | |
| // Load AI models from API (simulated) | |
| async function loadAIModels() { | |
| // In a real app, this would fetch from your API | |
| return new Promise(resolve => { | |
| setTimeout(() => { | |
| resolve([ | |
| { id: 'stable-diffusion-v2', name: 'Stable Diffusion v2', description: 'Best for general purpose generations' }, | |
| { id: 'dall-e-3', name: 'DALL-E 3', description: 'Best for creative and artistic generations' }, | |
| { id: 'midjourney-v5', name: 'Midjourney v5', description: 'Best for photorealistic images' } | |
| ]); | |
| }, 500); | |
| }); | |
| } | |
| // Initialize AI models dropdown | |
| if (document.querySelector('#ai-model')) { | |
| const models = await loadAIModels(); | |
| const modelSelect = document.querySelector('#ai-model'); | |
| models.forEach(model => { | |
| const option = document.createElement('option'); | |
| option.value = model.id; | |
| option.textContent = model.name; | |
| modelSelect.appendChild(option); | |
| }); | |
| } | |
| // Initialize file upload functionality | |
| const uploadArea = document.querySelector('.border-dashed'); | |
| const fileInput = document.querySelector('input[type="file"]'); | |
| uploadArea.addEventListener('click', () => fileInput.click()); | |
| uploadArea.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| uploadArea.classList.add('border-primary', 'bg-gray-700/50'); | |
| }); | |
| uploadArea.addEventListener('dragleave', () => { | |
| uploadArea.classList.remove('border-primary', 'bg-gray-700/50'); | |
| }); | |
| uploadArea.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| uploadArea.classList.remove('border-primary', 'bg-gray-700/50'); | |
| if (e.dataTransfer.files.length) { | |
| fileInput.files = e.dataTransfer.files; | |
| handleFileUpload(e.dataTransfer.files[0]); | |
| } | |
| }); | |
| fileInput.addEventListener('change', () => { | |
| if (fileInput.files.length) { | |
| handleFileUpload(fileInput.files[0]); | |
| } | |
| }); | |
| }); | |
| function handleFileUpload(file) { | |
| // In a real app, you would handle the file upload here | |
| console.log('File selected:', file.name); | |
| // Preview the image | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| const uploadArea = document.querySelector('.border-dashed'); | |
| uploadArea.innerHTML = ` | |
| <img src="${e.target.result}" class="max-h-48 mx-auto rounded-md" alt="Preview"> | |
| <p class="text-sm text-gray-300 mt-2">${file.name}</p> | |
| `; | |
| }; | |
| reader.readAsDataURL(file); | |
| } | |
| // Creative random prompt generator with more variety | |
| const promptTemplates = [ | |
| "{color} {mood} {subject} in {environment} with {style} style, {lighting} lighting, {perspective} view", | |
| "{adjective} {subject} in {timeOfDay} with {colorScheme} colors, {artStyle} style", | |
| "{artStyle} of {subject} in {worldType}, {mood} atmosphere, {weather} weather", | |
| "{perspective} view of {subject} with {lighting} lighting, {artStyle} style", | |
| "{subject} in {location}, {timePeriod} {style} style, {mood} atmosphere", | |
| "A {adjective} {subject} {action} in {environment}, {artStyle} style", | |
| "{subject} {action} during {timeOfDay} in {location}, {style} style" | |
| ]; | |
| const promptWords = { | |
| subject: ["dragon", "castle", "forest", "robot", "spaceship", "samurai", "wizard", "city", "ocean", "beast", | |
| "knight", "unicorn", "cyborg", "mermaid", "phoenix", "dinosaur", "alien", "ghost", "angel", "demon"], | |
| mood: ["mystical", "dramatic", "serene", "chaotic", "moody", "whimsical", "dark", "light", "surreal", | |
| "epic", "romantic", "ominous", "joyful", "melancholic", "energetic", "peaceful"], | |
| environment: ["misty mountains", "cyberpunk alley", "ancient ruins", "crystal caves", "floating islands", | |
| "underground city", "magical library", "space station", "enchanted forest", "haunted mansion"], | |
| color: ["red", "blue", "golden", "silver", "purple", "emerald", "rainbow", "pastel", "neon", "monochrome"], | |
| adjective: ["glowing", "ethereal", "futuristic", "ancient", "majestic", "tiny", "gigantic", "mysterious", | |
| "legendary", "forgotten", "hidden", "celestial", "mechanical", "organic", "crystalline"], | |
| timeOfDay: ["sunrise", "midnight", "golden hour", "blue hour", "noon", "twilight", "dawn", "dusk"], | |
| colorScheme: ["monochromatic", "complementary", "analogous", "warm", "cool", "triadic", "tetradic"], | |
| artStyle: ["Painting", "Sculpture", "Digital art", "Watercolor", "Oil painting", "Charcoal sketch", | |
| "Pixel art", "Anime", "Concept art", "Surrealist", "Impressionist", "Abstract"], | |
| worldType: ["fantasy world", "sci-fi universe", "post-apocalyptic wasteland", "alien planet", | |
| "steampunk city", "dream realm", "underwater kingdom", "floating continent"], | |
| perspective: ["Close-up", "Wide angle", "Birds-eye", "Worms-eye", "Tilted", "Macro", "Fisheye", "Panoramic"], | |
| lighting: ["volumetric", "neon", "natural", "bioluminescent", "chiaroscuro", "moonlight", "sunbeams", | |
| "candlelight", "strobe", "firelight"], | |
| location: ["Paris", "Tokyo", "New York", "African savanna", "Amazon rainforest", "Himalayas", | |
| "Great Barrier Reef", "Sahara Desert", "Antarctica", "Venice"], | |
| timePeriod: ["medieval", "Victorian", "1920s", "futuristic", "Stone age", "Renaissance", "Ancient Egypt", | |
| "Wild West", "Space Age", "Prehistoric"], | |
| style: ["photorealistic", "concept art", "character design", "editorial", "minimalist", "hyperrealistic", | |
| "low poly", "isometric", "line art", "graffiti"], | |
| weather: ["rainy", "sunny", "foggy", "stormy", "snowy", "windy", "cloudy", "aurora-filled"], | |
| action: ["flying", "battling", "meditating", "exploring", "dancing", "singing", "casting spells", | |
| "building", "destroying", "protecting"] | |
| }; | |
| function generateRandomPrompt() { | |
| const template = promptTemplates[Math.floor(Math.random() * promptTemplates.length)]; | |
| let prompt = template.replace(/{([^}]+)}/g, (match, key) => { | |
| const words = promptWords[key]; | |
| return words ? words[Math.floor(Math.random() * words.length)] : match; | |
| }); | |
| // Add some random artistic modifiers 50% of the time | |
| if (Math.random() > 0.5) { | |
| const modifiers = [ | |
| "trending on artstation", | |
| "4k resolution", | |
| "highly detailed", | |
| "intricate details", | |
| "cinematic lighting", | |
| "octane render", | |
| "unreal engine", | |
| "8k wallpaper", | |
| "sharp focus", | |
| "studio quality" | |
| ]; | |
| prompt += `, ${modifiers[Math.floor(Math.random() * modifiers.length)]}`; | |
| } | |
| return prompt; | |
| } | |
| document.getElementById('random-prompt').addEventListener('click', function() { | |
| const promptInput = document.getElementById('prompt-input'); | |
| promptInput.value = generateRandomPrompt(); | |
| promptInput.focus(); | |
| }); | |
| // Generate button functionality | |
| document.querySelector('.bg-gradient-to-r').addEventListener('click', function() { | |
| // In a real app, this would call your AI generation API | |
| console.log('Generating images...'); | |
| // Simulate loading | |
| const button = this; | |
| const originalText = button.innerHTML; | |
| button.innerHTML = '<i data-feather="loader" class="animate-spin w-4 h-4 mr-2"></i> Generating...'; | |
| button.disabled = true; | |
| // Simulate API call | |
| setTimeout(() => { | |
| button.innerHTML = originalText; | |
| button.disabled = false; | |
| // Simulate generated images | |
| const generatedImages = [ | |
| 'http://static.photos/abstract/640x360/' + Math.floor(Math.random() * 100), | |
| 'http://static.photos/abstract/640x360/' + Math.floor(Math.random() * 100) | |
| ]; | |
| // Save to history | |
| const prompt = document.querySelector('textarea').value || 'Untitled generation'; | |
| const model = document.querySelector('#ai-model').value; | |
| const style = document.querySelector('#style-select').value; | |
| aiManager.saveGeneration(prompt, generatedImages, { | |
| model, | |
| style | |
| }); | |
| // Show success message | |
| const success = document.createElement('div'); | |
| success.className = 'fixed top-4 right-4 bg-green-500 text-white px-4 py-2 rounded-md shadow-lg'; | |
| success.innerHTML = '<i data-feather="check-circle" class="w-4 h-4 inline mr-2"></i> Images generated successfully!'; | |
| document.body.appendChild(success); | |
| // Show results section with generated images | |
| const resultsSection = document.getElementById('results'); | |
| resultsSection.classList.remove('hidden'); | |
| resultsSection.scrollIntoView({ behavior: 'smooth' }); | |
| // Update the images | |
| const previews = document.querySelectorAll('image-preview'); | |
| previews[0].setAttribute('src', generatedImages[0]); | |
| previews[0].setAttribute('ai-generated', 'true'); | |
| previews[1].setAttribute('src', generatedImages[1]); | |
| previews[1].setAttribute('ai-generated', 'true'); | |
| // Refresh icons (since we added new ones) | |
| feather.replace(); | |
| // Remove message after 3 seconds | |
| setTimeout(() => success.remove(), 3000); | |
| }, 2000); | |
| }); |