Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>ArtFlow - Creative Image & Video Generator</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #6e8efb, #a777e3); | |
| } | |
| .generation-card { | |
| transition: all 0.3s ease; | |
| box-shadow: 0 10px 20px rgba(0,0,0,0.1); | |
| } | |
| .generation-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 15px 30px rgba(0,0,0,0.2); | |
| } | |
| .progress-bar { | |
| height: 6px; | |
| transition: width 0.3s ease; | |
| } | |
| .video-preview { | |
| aspect-ratio: 16/9; | |
| } | |
| .drawer { | |
| transition: transform 0.3s ease; | |
| } | |
| .drawer.closed { | |
| transform: translateX(100%); | |
| } | |
| #imageGrid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); | |
| gap: 1rem; | |
| } | |
| @media (max-width: 768px) { | |
| #imageGrid { | |
| grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); | |
| } | |
| } | |
| /* Custom animation for generated images */ | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: scale(0.95); } | |
| to { opacity: 1; transform: scale(1); } | |
| } | |
| .generated-image { | |
| animation: fadeIn 0.5s ease-out forwards; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen"> | |
| <!-- Navigation --> | |
| <nav class="bg-white shadow-sm"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="flex justify-between h-16"> | |
| <div class="flex items-center"> | |
| <div class="flex-shrink-0 flex items-center"> | |
| <i class="fas fa-magic text-purple-600 text-2xl mr-2"></i> | |
| <span class="text-xl font-bold text-gray-900">ArtFlow</span> | |
| </div> | |
| </div> | |
| <div class="hidden md:ml-6 md:flex md:items-center md:space-x-8"> | |
| <a href="#" class="text-purple-600 border-b-2 border-purple-600 px-3 py-2 text-sm font-medium">Generate</a> | |
| <a href="#" class="text-gray-500 hover:text-gray-700 px-3 py-2 text-sm font-medium">My Creations</a> | |
| <a href="#" class="text-gray-500 hover:text-gray-700 px-3 py-2 text-sm font-medium">Pricing</a> | |
| <a href="#" class="text-gray-500 hover:text-gray-700 px-3 py-2 text-sm font-medium">Community</a> | |
| </div> | |
| <div class="flex items-center"> | |
| <div class="flex-shrink-0 flex items-center"> | |
| <span class="mr-4 text-sm font-medium text-gray-500">Credits: <span id="creditsCounter" class="text-purple-600 font-bold">100</span>/100</span> | |
| <button class="px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"> | |
| Upgrade | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- Main Content --> | |
| <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> | |
| <div class="flex flex-col lg:flex-row gap-8"> | |
| <!-- Left Sidebar - Generation Controls --> | |
| <div class="w-full lg:w-1/3 space-y-6"> | |
| <div class="bg-white rounded-lg shadow-sm p-6 generation-card"> | |
| <h2 class="text-lg font-medium text-gray-900 mb-4">Create Magic</h2> | |
| <div class="space-y-4"> | |
| <div> | |
| <label for="prompt" class="block text-sm font-medium text-gray-700 mb-1">Describe your vision</label> | |
| <textarea id="prompt" rows="3" class="shadow-sm focus:ring-purple-500 focus:border-purple-500 block w-full sm:text-sm border border-gray-300 rounded-md p-3" placeholder="A futuristic city with flying cars, neon lights, cyberpunk style...">human man holding an alien baby</textarea> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Content Type</label> | |
| <div class="flex space-x-4"> | |
| <button id="imageBtn" class="flex-1 py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"> | |
| Image | |
| </button> | |
| <button id="videoBtn" class="flex-1 py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"> | |
| Video | |
| </button> | |
| </div> | |
| </div> | |
| <div id="imageOptions"> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div> | |
| <label for="style" class="block text-sm font-medium text-gray-700 mb-1">Style</label> | |
| <select id="style" class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm rounded-md"> | |
| <option>Realistic</option> | |
| <option>Anime</option> | |
| <option>Painting</option> | |
| <option>Cyberpunk</option> | |
| <option>Fantasy</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label for="quality" class="block text-sm font-medium text-gray-700 mb-1">Quality</label> | |
| <select id="quality" class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm rounded-md"> | |
| <option>Standard</option> | |
| <option>High</option> | |
| <option>Ultra</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="mt-4"> | |
| <label for="numImages" class="block text-sm font-medium text-gray-700 mb-1">Number of Images (Max 4 at a time)</label> | |
| <input type="range" id="numImages" min="1" max="4" value="1" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> | |
| <div class="flex justify-between text-xs text-gray-500 mt-1"> | |
| <span>1</span> | |
| <span>2</span> | |
| <span>3</span> | |
| <span>4</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="videoOptions" class="hidden"> | |
| <div> | |
| <label for="videoLength" class="block text-sm font-medium text-gray-700 mb-1">Video Length (Max 20 minutes)</label> | |
| <input type="range" id="videoLength" min="1" max="20" value="5" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> | |
| <div class="flex justify-between text-xs text-gray-500 mt-1"> | |
| <span>1 min</span> | |
| <span>5 min</span> | |
| <span>10 min</span> | |
| <span>15 min</span> | |
| <span>20 min</span> | |
| </div> | |
| </div> | |
| <div class="mt-4"> | |
| <label for="videoStyle" class="block text-sm font-medium text-gray-700 mb-1">Animation Style</label> | |
| <select id="videoStyle" class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm rounded-md"> | |
| <option>Smooth Motion</option> | |
| <option>Anime Style</option> | |
| <option>Stop Motion</option> | |
| <option>Claymation</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="pt-2"> | |
| <button id="generateBtn" class="w-full flex justify-center py-3 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"> | |
| <i class="fas fa-sparkle mr-2"></i> Generate Now | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white rounded-lg shadow-sm p-6 generation-card"> | |
| <h2 class="text-lg font-medium text-gray-900 mb-4">Daily Usage</h2> | |
| <div class="space-y-4"> | |
| <div> | |
| <div class="flex justify-between text-sm font-medium text-gray-700 mb-1"> | |
| <span>Image Generations</span> | |
| <span><span id="imagesUsed">1</span>/100</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2.5"> | |
| <div id="imageProgress" class="bg-purple-600 h-2.5 rounded-full" style="width: 1%"></div> | |
| </div> | |
| </div> | |
| <div> | |
| <div class="flex justify-between text-sm font-medium text-gray-700 mb-1"> | |
| <span>Video Minutes</span> | |
| <span><span id="minutesUsed">0</span>/20</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2.5"> | |
| <div id="videoProgress" class="bg-indigo-600 h-2.5 rounded-full" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Right Content - Results --> | |
| <div class="w-full lg:w-2/3 space-y-6"> | |
| <div class="bg-white rounded-lg shadow-sm p-6"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h2 class="text-lg font-medium text-gray-900">Your Creations</h2> | |
| <div class="flex space-x-2"> | |
| <button class="p-2 rounded-md hover:bg-gray-100"> | |
| <i class="fas fa-grid text-gray-500"></i> | |
| </button> | |
| <button class="p-2 rounded-md hover:bg-gray-100"> | |
| <i class="fas fa-list text-gray-500"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Results will appear here --> | |
| <div id="resultsArea" class="space-y-6"> | |
| <div id="emptyState" class="text-center py-12"> | |
| <i class="fas fa-sparkle text-4xl text-purple-200 mb-4"></i> | |
| <h3 class="text-lg font-medium text-gray-900 mb-1">Nothing here yet</h3> | |
| <p class="text-gray-500">Describe your vision and click "Generate Now" to create something amazing!</p> | |
| </div> | |
| <div id="loadingState" class="hidden text-center py-12"> | |
| <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-purple-600 mx-auto mb-4"></div> | |
| <h3 class="text-lg font-medium text-gray-900 mb-1">Creating your masterpiece</h3> | |
| <p class="text-gray-500">This usually takes 20-45 seconds. Please wait...</p> | |
| <div class="w-full bg-gray-200 rounded-full h-1.5 mt-4"> | |
| <div id="generationProgress" class="bg-purple-600 h-1.5 rounded-full" style="width: 0%"></div> | |
| </div> | |
| </div> | |
| <div id="imageResults" class="hidden"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-md font-medium text-gray-900">Generated Images</h3> | |
| <button id="downloadAllBtn" class="text-sm text-purple-600 hover:text-purple-800 font-medium"> | |
| <i class="fas fa-download mr-1"></i> Download All | |
| </button> | |
| </div> | |
| <div id="imageGrid" class="grid grid-cols-2 md:grid-cols-3 gap-4"> | |
| <!-- Images will be added here by JavaScript --> | |
| </div> | |
| </div> | |
| <div id="videoResults" class="hidden"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-md font-medium text-gray-900">Generated Video</h3> | |
| <div class="space-x-2"> | |
| <button class="text-sm text-purple-600 hover:text-purple-800 font-medium"> | |
| <i class="fas fa-download mr-1"></i> Download | |
| </button> | |
| <button class="text-sm text-purple-600 hover:text-purple-800 font-medium"> | |
| <i class="fas fa-share-alt mr-1"></i> Share | |
| </button> | |
| </div> | |
| </div> | |
| <div class="video-preview bg-gray-100 rounded-lg overflow-hidden flex items-center justify-center"> | |
| <div id="videoPlayer" class="w-full"> | |
| <!-- Video will be inserted here by JavaScript --> | |
| </div> | |
| </div> | |
| <div class="mt-4 flex justify-between items-center"> | |
| <div> | |
| <p class="text-sm text-gray-500">Duration: <span id="videoDuration">0</span> minutes</p> | |
| </div> | |
| <div class="flex space-x-2"> | |
| <button class="p-2 rounded-md hover:bg-gray-100"> | |
| <i class="fas fa-edit text-gray-500"></i> | |
| </button> | |
| <button class="p-2 rounded-md hover:bg-gray-100"> | |
| <i class="fas fa-trash text-gray-500"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-white rounded-lg shadow-sm p-6"> | |
| <h2 class="text-lg font-medium text-gray-900 mb-4">Recent Creations</h2> | |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4"> | |
| <div class="group relative aspect-square bg-gray-100 rounded-lg overflow-hidden cursor-pointer"> | |
| <img src="https://images.unsplash.com/photo-1682686580391-615b3f8279b0?w=500&auto=format&fit=crop" class="w-full h-full object-cover"> | |
| <div class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-30 transition-all duration-200 flex items-center justify-center"> | |
| <button class="expand-btn opacity-0 group-hover:opacity-100 transform translate-y-2 group-hover:translate-y-0 transition-all duration-200 text-white bg-purple-600 hover:bg-purple-700 rounded-full p-2"> | |
| <i class="fas fa-expand"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="group relative aspect-square bg-gray-100 rounded-lg overflow-hidden cursor-pointer"> | |
| <div class="absolute inset-0 flex items-center justify-center"> | |
| <i class="fas fa-play text-gray-300 text-3xl"></i> | |
| </div> | |
| <div class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-30 transition-all duration-200 flex items-center justify-center"> | |
| <button class="opacity-0 group-hover:opacity-100 transform translate-y-2 group-hover:translate-y-0 transition-all duration-200 text-white bg-purple-600 hover:bg-purple-700 rounded-full p-2"> | |
| <i class="fas fa-expand"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="group relative aspect-square bg-gray-100 rounded-lg overflow-hidden cursor-pointer"> | |
| <img src="https://images.unsplash.com/photo-1682695796954-bad0d0f59ff1?w=500&auto=format&fit=crop" class="w-full h-full object-cover"> | |
| <div class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-30 transition-all duration-200 flex items-center justify-center"> | |
| <button class="expand-btn opacity-0 group-hover:opacity-100 transform translate-y-2 group-hover:translate-y-0 transition-all duration-200 text-white bg-purple-600 hover:bg-purple-700 rounded-full p-2"> | |
| <i class="fas fa-expand"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="group relative aspect-square bg-gray-100 rounded-lg overflow-hidden cursor-pointer"> | |
| <div class="absolute inset-0 flex items-center justify-center"> | |
| <i class="fas fa-play text-gray-300 text-3xl"></i> | |
| </div> | |
| <div class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-30 transition-all duration-200 flex items-center justify-center"> | |
| <button class="opacity-0 group-hover:opacity-100 transform translate-y-2 group-hover:translate-y-0 transition-all duration-200 text-white bg-purple-600 hover:bg-purple-700 rounded-full p-2"> | |
| <i class="fas fa-expand"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Footer --> | |
| <footer class="bg-white border-t border-gray-200 mt-12"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> | |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-8"> | |
| <div> | |
| <h3 class="text-sm font-semibold text-gray-900 tracking-wider uppercase mb-4">ArtFlow</h3> | |
| <p class="text-sm text-gray-500">The easiest way to create stunning visuals and animations for your stories and projects.</p> | |
| </div> | |
| <div> | |
| <h3 class="text-sm font-semibold text-gray-900 tracking-wider uppercase mb-4">Product</h3> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Features</a></li> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Pricing</a></li> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">API</a></li> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Changelog</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h3 class="text-sm font-semibold text-gray-900 tracking-wider uppercase mb-4">Resources</h3> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Documentation</a></li> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Community</a></li> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Tutorials</a></li> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Blog</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h3 class="text-sm font-semibold text-gray-900 tracking-wider uppercase mb-4">Company</h3> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">About</a></li> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Careers</a></li> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Privacy</a></li> | |
| <li><a href="#" class="text-sm text-gray-500 hover:text-purple-600">Terms</a></li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div class="mt-8 pt-8 border-t border-gray-200 flex flex-col md:flex-row justify-between items-center"> | |
| <p class="text-sm text-gray-500">© 2023 ArtFlow. All rights reserved.</p> | |
| <div class="flex space-x-6 mt-4 md:mt-0"> | |
| <a href="#" class="text-gray-400 hover:text-gray-500"> | |
| <i class="fab fa-twitter"></i> | |
| </a> | |
| <a href="#" class="text-gray-400 hover:text-gray-500"> | |
| <i class="fab fa-discord"></i> | |
| </a> | |
| <a href="#" class="text-gray-400 hover:text-gray-500"> | |
| <i class="fab fa-github"></i> | |
| </a> | |
| <a href="#" class="text-gray-400 hover:text-gray-500"> | |
| <i class="fab fa-instagram"></i> | |
| </a> | |
| </div> | |
| </div> | |
| </div> | |
| </footer> | |
| <!-- Image Preview Modal --> | |
| <div id="imageModal" class="fixed inset-0 z-50 hidden overflow-y-auto"> | |
| <div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> | |
| <div class="fixed inset-0 transition-opacity" aria-hidden="true"> | |
| <div class="absolute inset-0 bg-gray-500 opacity-75"></div> | |
| </div> | |
| <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span> | |
| <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:w-full"> | |
| <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> | |
| <div class="sm:flex sm:items-start"> | |
| <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">Image Preview</h3> | |
| <button id="closeModal" class="text-gray-400 hover:text-gray-500"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="mt-2"> | |
| <img id="modalImage" src="" alt="Preview" class="w-full h-auto max-h-[70vh] object-contain"> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> | |
| <button type="button" id="downloadModalBtn" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-purple-600 text-base font-medium text-white hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500 sm:ml-3 sm:w-auto sm:text-sm"> | |
| <i class="fas fa-download mr-2"></i> Download | |
| </button> | |
| <button type="button" id="closeModalBtn" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"> | |
| Close | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // DOM Elements | |
| const imageBtn = document.getElementById('imageBtn'); | |
| const videoBtn = document.getElementById('videoBtn'); | |
| const imageOptions = document.getElementById('imageOptions'); | |
| const videoOptions = document.getElementById('videoOptions'); | |
| const generateBtn = document.getElementById('generateBtn'); | |
| const emptyState = document.getElementById('emptyState'); | |
| const loadingState = document.getElementById('loadingState'); | |
| const imageResults = document.getElementById('imageResults'); | |
| const videoResults = document.getElementById('videoResults'); | |
| const imageGrid = document.getElementById('imageGrid'); | |
| const videoPlayer = document.getElementById('videoPlayer'); | |
| const creditsCounter = document.getElementById('creditsCounter'); | |
| const imagesUsed = document.getElementById('imagesUsed'); | |
| const minutesUsed = document.getElementById('minutesUsed'); | |
| const imageProgress = document.getElementById('imageProgress'); | |
| const videoProgress = document.getElementById('videoProgress'); | |
| const generationProgress = document.getElementById('generationProgress'); | |
| const numImages = document.getElementById('numImages'); | |
| const videoLength = document.getElementById('videoLength'); | |
| const videoDuration = document.getElementById('videoDuration'); | |
| const downloadAllBtn = document.getElementById('downloadAllBtn'); | |
| const promptInput = document.getElementById('prompt'); | |
| const styleSelect = document.getElementById('style'); | |
| const qualitySelect = document.getElementById('quality'); | |
| // Modal elements | |
| const imageModal = document.getElementById('imageModal'); | |
| const modalImage = document.getElementById('modalImage'); | |
| const closeModal = document.getElementById('closeModal'); | |
| const closeModalBtn = document.getElementById('closeModalBtn'); | |
| const downloadModalBtn = document.getElementById('downloadModalBtn'); | |
| // State | |
| let isGenerating = false; | |
| let currentMode = 'image'; // 'image' or 'video' | |
| let usedImagesToday = 1; // Starting with 1 as per request | |
| let usedMinutesToday = 0; | |
| let credits = 100; | |
| // Sample image URLs for demonstration | |
| const sampleImages = [ | |
| 'https://images.unsplash.com/photo-1682686580391-615b3f8279b0?w=500&auto=format&fit=crop', | |
| 'https://images.unsplash.com/photo-1682695796954-bad0d0f59ff1?w=500&auto=format&fit=crop', | |
| 'https://images.unsplash.com/photo-1682686580391-615b3f8279b0?w=500&auto=format&fit=crop', | |
| 'https://images.unsplash.com/photo-1682695796954-bad0d0f59ff1?w=500&auto=format&fit=crop' | |
| ]; | |
| // Sample video for demonstration | |
| const sampleVideo = '<video controls class="w-full h-full"><source src="https://samplelib.com/lib/preview/mp4/sample-5s.mp4" type="video/mp4"></video>'; | |
| // Event Listeners | |
| imageBtn.addEventListener('click', () => { | |
| currentMode = 'image'; | |
| imageBtn.classList.remove('bg-white', 'text-gray-700', 'border-gray-300'); | |
| imageBtn.classList.add('bg-purple-600', 'text-white'); | |
| videoBtn.classList.remove('bg-purple-600', 'text-white'); | |
| videoBtn.classList.add('bg-white', 'text-gray-700', 'border-gray-300'); | |
| imageOptions.classList.remove('hidden'); | |
| videoOptions.classList.add('hidden'); | |
| imageResults.classList.remove('hidden'); | |
| videoResults.classList.add('hidden'); | |
| }); | |
| videoBtn.addEventListener('click', () => { | |
| currentMode = 'video'; | |
| videoBtn.classList.remove('bg-white', 'text-gray-700', 'border-gray-300'); | |
| videoBtn.classList.add('bg-purple-600', 'text-white'); | |
| imageBtn.classList.remove('bg-purple-600', 'text-white'); | |
| imageBtn.classList.add('bg-white', 'text-gray-700', 'border-gray-300'); | |
| videoOptions.classList.remove('hidden'); | |
| imageOptions.classList.add('hidden'); | |
| videoResults.classList.remove('hidden'); | |
| imageResults.classList.add('hidden'); | |
| }); | |
| generateBtn.addEventListener('click', () => { | |
| if (isGenerating) return; | |
| const prompt = promptInput.value.trim(); | |
| if (!prompt) { | |
| alert('Please enter a description for your generation'); | |
| return; | |
| } | |
| if (currentMode === 'image') { | |
| const num = parseInt(numImages.value); | |
| if (usedImagesToday + num > 100) { | |
| alert(`You can only generate ${100 - usedImagesToday} more images today`); | |
| return; | |
| } | |
| } else { | |
| const minutes = parseInt(videoLength.value); | |
| if (usedMinutesToday + minutes > 20) { | |
| alert(`You can only generate ${20 - usedMinutesToday} more minutes of video today`); | |
| return; | |
| } | |
| } | |
| startGeneration(); | |
| }); | |
| downloadAllBtn.addEventListener('click', () => { | |
| alert('All images will be downloaded as a ZIP file'); | |
| }); | |
| // Handle image clicks for preview and download | |
| document.addEventListener('click', (e) => { | |
| // Handle expand button clicks | |
| if (e.target.classList.contains('expand-btn') || e.target.closest('.expand-btn')) { | |
| const imgElement = e.target.closest('.group').querySelector('img'); | |
| if (imgElement) { | |
| openImageModal(imgElement.src); | |
| } | |
| } | |
| // Handle download button clicks | |
| if (e.target.classList.contains('download-btn') || e.target.closest('.download-btn')) { | |
| const imgElement = e.target.closest('.group').querySelector('img'); | |
| if (imgElement) { | |
| downloadImage(imgElement.src); | |
| } | |
| } | |
| }); | |
| // Modal event listeners | |
| closeModal.addEventListener('click', () => { | |
| imageModal.classList.add('hidden'); | |
| }); | |
| closeModalBtn.addEventListener('click', () => { | |
| imageModal.classList.add('hidden'); | |
| }); | |
| downloadModalBtn.addEventListener('click', () => { | |
| downloadImage(modalImage.src); | |
| }); | |
| // Functions | |
| function startGeneration() { | |
| isGenerating = true; | |
| emptyState.classList.add('hidden'); | |
| loadingState.classList.remove('hidden'); | |
| imageResults.classList.add('hidden'); | |
| videoResults.classList.add('hidden'); | |
| // Simulate generation progress | |
| let progress = 0; | |
| const interval = setInterval(() => { | |
| progress += Math.random() * 10; | |
| if (progress > 100) progress = 100; | |
| generationProgress.style.width = `${progress}%`; | |
| if (progress >= 100) { | |
| clearInterval(interval); | |
| finishGeneration(); | |
| } | |
| }, 300); | |
| } | |
| function finishGeneration() { | |
| isGenerating = false; | |
| loadingState.classList.add('hidden'); | |
| if (currentMode === 'image') { | |
| const num = parseInt(numImages.value); | |
| usedImagesToday += num; | |
| credits -= num; | |
| // Update UI | |
| imagesUsed.textContent = usedImagesToday; | |
| creditsCounter.textContent = credits; | |
| imageProgress.style.width = `${(usedImagesToday / 100) * 100}%`; | |
| // Display results | |
| imageGrid.innerHTML = ''; | |
| for (let i = 0; i < num; i++) { | |
| // Generate a unique image based on prompt and settings | |
| const prompt = promptInput.value; | |
| const style = styleSelect.value; | |
| const quality = qualitySelect.value; | |
| // In a real app, this would call an API to generate the image | |
| // For demo, we'll use sample images with different cache-busting parameters | |
| const imgUrl = getGeneratedImageUrl(prompt, style, quality, i); | |
| imageGrid.innerHTML += ` | |
| <div class="group relative aspect-square bg-gray-100 rounded-lg overflow-hidden generated-image"> | |
| <img src="${imgUrl}" alt="Generated image" class="w-full h-full object-cover"> | |
| <div class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-30 transition-all duration-200 flex items-center justify-center opacity-0 group-hover:opacity-100"> | |
| <div class="flex space-x-2"> | |
| <button class="download-btn text-white bg-purple-600 hover:bg-purple-700 rounded-full p-2"> | |
| <i class="fas fa-download"></i> | |
| </button> | |
| <button class="expand-btn text-white bg-purple-600 hover:bg-purple-700 rounded-full p-2"> | |
| <i class="fas fa-expand"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| imageResults.classList.remove('hidden'); | |
| } else { | |
| const minutes = parseInt(videoLength.value); | |
| usedMinutesToday += minutes; | |
| credits -= minutes; | |
| // Update UI | |
| minutesUsed.textContent = usedMinutesToday; | |
| creditsCounter.textContent = credits; | |
| videoProgress.style.width = `${(usedMinutesToday / 20) * 100}%`; | |
| videoDuration.textContent = minutes; | |
| // Display results | |
| videoPlayer.innerHTML = sampleVideo; | |
| videoResults.classList.remove('hidden'); | |
| } | |
| } | |
| function getGeneratedImageUrl(prompt, style, quality, index) { | |
| // In a real app, this would call an API to generate the image | |
| // For demo purposes, we'll return different sample images based on parameters | |
| const baseUrl = sampleImages[index % sampleImages.length]; | |
| return `${baseUrl}&prompt=${encodeURIComponent(prompt)}&style=${style}&quality=${quality}&t=${Date.now()}`; | |
| } | |
| function openImageModal(imageUrl) { | |
| modalImage.src = imageUrl; | |
| imageModal.classList.remove('hidden'); | |
| } | |
| function downloadImage(imageUrl) { | |
| // In a real app, this would properly download the image | |
| // For demo, we'll just show an alert | |
| alert(`Downloading image: ${imageUrl.split('?')[0]}`); | |
| // This would be the actual download code: | |
| /* | |
| const link = document.createElement('a'); | |
| link.href = imageUrl; | |
| link.download = `artflow-${Date.now()}.jpg`; | |
| document.body.appendChild(link); | |
| link.click(); | |
| document.body.removeChild(link); | |
| */ | |
| } | |
| // Initialize | |
| imageBtn.click(); // Set default to image mode | |
| imageProgress.style.width = `${(usedImagesToday / 100) * 100}%`; // Set initial progress | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=theaimoron/aet-flow" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |