|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>NeonDream AI - Image 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> |
|
|
|
.window-shadow { |
|
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); |
|
} |
|
.neon-shadow { |
|
box-shadow: 0 0 10px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.3); |
|
} |
|
.title-bar { |
|
-webkit-user-select: none; |
|
user-select: none; |
|
background: linear-gradient(90deg, #1e293b, #334155); |
|
} |
|
.draggable { |
|
-webkit-app-region: drag; |
|
} |
|
.resizable { |
|
resize: both; |
|
overflow: auto; |
|
min-width: 400px; |
|
min-height: 500px; |
|
} |
|
.scrollbar-hide::-webkit-scrollbar { |
|
display: none; |
|
} |
|
.scrollbar-hide { |
|
-ms-overflow-style: none; |
|
scrollbar-width: none; |
|
} |
|
.fade-in { |
|
animation: fadeIn 0.3s ease-in-out; |
|
} |
|
.pulse { |
|
animation: pulse 2s infinite; |
|
} |
|
@keyframes fadeIn { |
|
from { opacity: 0; transform: translateY(10px); } |
|
to { opacity: 1; transform: translateY(0); } |
|
} |
|
@keyframes pulse { |
|
0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7); } |
|
70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); } |
|
100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); } |
|
} |
|
.gradient-border { |
|
position: relative; |
|
border-radius: 0.5rem; |
|
} |
|
.gradient-border::before { |
|
content: ''; |
|
position: absolute; |
|
top: -2px; |
|
left: -2px; |
|
right: -2px; |
|
bottom: -2px; |
|
background: linear-gradient(45deg, #3b82f6, #8b5cf6, #ec4899); |
|
border-radius: 0.5rem; |
|
z-index: -1; |
|
opacity: 0; |
|
transition: opacity 0.3s; |
|
} |
|
.gradient-border:hover::before { |
|
opacity: 1; |
|
} |
|
.typewriter { |
|
overflow: hidden; |
|
border-right: 2px solid #3b82f6; |
|
white-space: nowrap; |
|
margin: 0 auto; |
|
letter-spacing: 1px; |
|
animation: typing 3.5s steps(40, end), blink-caret 0.75s step-end infinite; |
|
} |
|
@keyframes typing { |
|
from { width: 0 } |
|
to { width: 100% } |
|
} |
|
@keyframes blink-caret { |
|
from, to { border-color: transparent } |
|
50% { border-color: #3b82f6 } |
|
} |
|
</style> |
|
</head> |
|
<body class="bg-gradient-to-br from-gray-900 to-gray-800 h-screen flex items-center justify-center p-4"> |
|
|
|
<div class="bg-gray-800 rounded-xl window-shadow resizable flex flex-col overflow-hidden w-full max-w-5xl h-[700px] border border-gray-700"> |
|
|
|
<div class="title-bar text-white px-4 py-3 flex justify-between items-center draggable rounded-t-xl"> |
|
<div class="flex items-center space-x-3"> |
|
<div class="relative"> |
|
<div class="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center neon-shadow pulse"> |
|
<i class="fas fa-brain text-white"></i> |
|
</div> |
|
<div class="absolute -bottom-1 -right-1 w-3 h-3 bg-green-400 rounded-full border-2 border-gray-800"></div> |
|
</div> |
|
<div> |
|
<h1 class="font-bold text-lg">NeonDream AI</h1> |
|
<p class="text-xs text-gray-300">Image Generator v2.4</p> |
|
</div> |
|
</div> |
|
<div class="flex space-x-2"> |
|
<button class="w-7 h-7 flex items-center justify-center hover:bg-gray-700 rounded-full transition"> |
|
<i class="fas fa-window-minimize text-xs"></i> |
|
</button> |
|
<button class="w-7 h-7 flex items-center justify-center hover:bg-gray-700 rounded-full transition"> |
|
<i class="fas fa-window-maximize text-xs"></i> |
|
</button> |
|
<button class="w-7 h-7 flex items-center justify-center hover:bg-red-500 rounded-full transition"> |
|
<i class="fas fa-times text-xs"></i> |
|
</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="bg-gray-700 border-b border-gray-600 flex px-3 py-1 text-sm"> |
|
<div class="px-3 py-1.5 hover:bg-gray-600 rounded-md cursor-pointer transition flex items-center space-x-1"> |
|
<i class="fas fa-folder text-blue-400 text-xs"></i> |
|
<span>File</span> |
|
</div> |
|
<div class="px-3 py-1.5 hover:bg-gray-600 rounded-md cursor-pointer transition flex items-center space-x-1"> |
|
<i class="fas fa-edit text-blue-400 text-xs"></i> |
|
<span>Edit</span> |
|
</div> |
|
<div class="px-3 py-1.5 hover:bg-gray-600 rounded-md cursor-pointer transition flex items-center space-x-1"> |
|
<i class="fas fa-eye text-blue-400 text-xs"></i> |
|
<span>View</span> |
|
</div> |
|
<div class="px-3 py-1.5 hover:bg-gray-600 rounded-md cursor-pointer transition flex items-center space-x-1"> |
|
<i class="fas fa-cog text-blue-400 text-xs"></i> |
|
<span>Settings</span> |
|
</div> |
|
<div class="px-3 py-1.5 hover:bg-gray-600 rounded-md cursor-pointer transition flex items-center space-x-1"> |
|
<i class="fas fa-question-circle text-blue-400 text-xs"></i> |
|
<span>Help</span> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="bg-gray-750 border-b border-gray-600 flex items-center px-4 py-2 space-x-3"> |
|
<button class="p-2 hover:bg-gray-700 rounded-md transition" title="New Project"> |
|
<i class="fas fa-file text-blue-400"></i> |
|
</button> |
|
<button class="p-2 hover:bg-gray-700 rounded-md transition" title="Save"> |
|
<i class="fas fa-save text-blue-400"></i> |
|
</button> |
|
<div class="h-6 w-px bg-gray-600 mx-1"></div> |
|
<button class="p-2 hover:bg-gray-700 rounded-md transition" title="Undo"> |
|
<i class="fas fa-undo text-blue-400"></i> |
|
</button> |
|
<button class="p-2 hover:bg-gray-700 rounded-md transition" title="Redo"> |
|
<i class="fas fa-redo text-blue-400"></i> |
|
</button> |
|
<div class="h-6 w-px bg-gray-600 mx-1"></div> |
|
<button id="openPromptBtn" class="flex items-center space-x-2 bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white px-4 py-2 rounded-md transition shadow-md gradient-border"> |
|
<i class="fas fa-magic"></i> |
|
<span>Generate Image</span> |
|
</button> |
|
<div class="flex-1"></div> |
|
<div class="text-xs text-gray-400 flex items-center space-x-2"> |
|
<div class="flex items-center space-x-1"> |
|
<div class="w-2 h-2 bg-green-400 rounded-full"></div> |
|
<span>Model Ready</span> |
|
</div> |
|
<span>•</span> |
|
<span>GPU: RTX 4090</span> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="flex-1 flex overflow-hidden"> |
|
|
|
<div class="w-56 bg-gray-750 border-r border-gray-600 p-3 overflow-y-auto scrollbar-hide"> |
|
<div class="flex items-center justify-between mb-3"> |
|
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Recent Prompts</div> |
|
<button class="text-xs text-blue-400 hover:text-blue-300 transition">Clear All</button> |
|
</div> |
|
<div class="space-y-2"> |
|
<div class="group relative"> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition flex items-center justify-between bg-gray-700"> |
|
<span class="truncate">A sunset over mountains</span> |
|
<i class="fas fa-redo text-gray-500 group-hover:text-blue-400 transition ml-2"></i> |
|
</div> |
|
</div> |
|
<div class="group relative"> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition flex items-center justify-between"> |
|
<span class="truncate">Cyberpunk city street</span> |
|
<i class="fas fa-redo text-gray-500 group-hover:text-blue-400 transition ml-2"></i> |
|
</div> |
|
</div> |
|
<div class="group relative"> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition flex items-center justify-between"> |
|
<span class="truncate">Portrait of a wizard</span> |
|
<i class="fas fa-redo text-gray-500 group-hover:text-blue-400 transition ml-2"></i> |
|
</div> |
|
</div> |
|
<div class="group relative"> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition flex items-center justify-between"> |
|
<span class="truncate">Futuristic spaceship</span> |
|
<i class="fas fa-redo text-gray-500 group-hover:text-blue-400 transition ml-2"></i> |
|
</div> |
|
</div> |
|
<div class="group relative"> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition flex items-center justify-between"> |
|
<span class="truncate">Cute cat wearing glasses</span> |
|
<i class="fas fa-redo text-gray-500 group-hover:text-blue-400 transition ml-2"></i> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="mt-6"> |
|
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-3">Preset Styles</div> |
|
<div class="grid grid-cols-2 gap-2"> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition bg-gray-700 text-center"> |
|
<i class="fas fa-mountain text-blue-400 mb-1"></i> |
|
<div class="text-xs">Landscape</div> |
|
</div> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition text-center"> |
|
<i class="fas fa-user text-blue-400 mb-1"></i> |
|
<div class="text-xs">Portrait</div> |
|
</div> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition text-center"> |
|
<i class="fas fa-dragon text-blue-400 mb-1"></i> |
|
<div class="text-xs">Fantasy</div> |
|
</div> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition text-center"> |
|
<i class="fas fa-robot text-blue-400 mb-1"></i> |
|
<div class="text-xs">Sci-Fi</div> |
|
</div> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition text-center"> |
|
<i class="fas fa-paint-brush text-blue-400 mb-1"></i> |
|
<div class="text-xs">Artistic</div> |
|
</div> |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition text-center"> |
|
<i class="fas fa-gamepad text-blue-400 mb-1"></i> |
|
<div class="text-xs">Pixel Art</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="mt-6"> |
|
<div class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-3">Quick Prompts</div> |
|
<div class="space-y-2"> |
|
<div class="p-2 text-xs hover:bg-gray-700 rounded-md cursor-pointer transition bg-gray-700"> |
|
"A futuristic city at night" |
|
</div> |
|
<div class="p-2 text-xs hover:bg-gray-700 rounded-md cursor-pointer transition"> |
|
"Watercolor landscape of mountains" |
|
</div> |
|
<div class="p-2 text-xs hover:bg-gray-700 rounded-md cursor-pointer transition"> |
|
"Cyberpunk character portrait" |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="flex-1 bg-gray-800 flex items-center justify-center overflow-auto p-6"> |
|
<div id="imageContainer" class="bg-gray-900 border-2 border-dashed border-gray-700 rounded-xl w-full h-full flex items-center justify-center relative"> |
|
<div class="text-center text-gray-500"> |
|
<i class="fas fa-image text-5xl mb-4 text-gray-600"></i> |
|
<p class="text-gray-400 mb-2">No image generated yet</p> |
|
<button id="quickGenerateBtn" class="text-blue-400 hover:text-blue-300 text-sm flex items-center justify-center mx-auto space-x-1 transition"> |
|
<i class="fas fa-bolt"></i> |
|
<span>Try a quick generation</span> |
|
</button> |
|
</div> |
|
|
|
<div id="imageControls" class="absolute bottom-4 right-4 bg-gray-800 rounded-full p-2 shadow-lg hidden"> |
|
<button class="w-8 h-8 bg-blue-600 hover:bg-blue-700 rounded-full flex items-center justify-center text-white transition"> |
|
<i class="fas fa-download text-sm"></i> |
|
</button> |
|
<button class="w-8 h-8 bg-gray-700 hover:bg-gray-600 rounded-full flex items-center justify-center text-white ml-2 transition"> |
|
<i class="fas fa-edit text-sm"></i> |
|
</button> |
|
<button class="w-8 h-8 bg-gray-700 hover:bg-gray-600 rounded-full flex items-center justify-center text-white ml-2 transition"> |
|
<i class="fas fa-share-alt text-sm"></i> |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="bg-gray-750 border-t border-gray-600 text-xs text-gray-400 px-4 py-2 flex justify-between items-center"> |
|
<div class="flex items-center space-x-4"> |
|
<div class="flex items-center space-x-1"> |
|
<i class="fas fa-microchip text-blue-400"></i> |
|
<span>VRAM: <span id="vramUsage">4.2</span>/24 GB</span> |
|
</div> |
|
<div class="flex items-center space-x-1"> |
|
<i class="fas fa-bolt text-yellow-400"></i> |
|
<span>GPU: <span id="gpuUsage">68</span>%</span> |
|
</div> |
|
<div class="flex items-center space-x-1"> |
|
<i class="fas fa-memory text-purple-400"></i> |
|
<span>RAM: <span id="ramUsage">5.7</span>/32 GB</span> |
|
</div> |
|
</div> |
|
<div class="flex items-center space-x-4"> |
|
<div class="flex items-center space-x-1"> |
|
<i class="fas fa-database text-green-400"></i> |
|
<span>Model: Stable Diffusion XL</span> |
|
</div> |
|
<div class="flex items-center space-x-1"> |
|
<i class="fas fa-clock text-gray-400"></i> |
|
<span id="currentTime">00:00:00</span> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div id="promptDialog" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center z-50 hidden backdrop-blur-sm"> |
|
<div class="bg-gray-800 rounded-xl window-shadow w-full max-w-xl fade-in border border-gray-700"> |
|
<div class="title-bar text-white px-4 py-3 flex justify-between items-center rounded-t-xl"> |
|
<div class="font-semibold flex items-center space-x-2"> |
|
<i class="fas fa-magic text-blue-400"></i> |
|
<span>Create New Image</span> |
|
</div> |
|
<button id="closePromptBtn" class="w-7 h-7 flex items-center justify-center hover:bg-red-500 rounded-full transition"> |
|
<i class="fas fa-times text-xs"></i> |
|
</button> |
|
</div> |
|
|
|
<div class="p-5"> |
|
<div class="mb-5"> |
|
<label class="block text-sm font-medium text-gray-300 mb-2">Describe your image</label> |
|
<div class="relative"> |
|
<textarea id="promptInput" class="w-full bg-gray-700 border border-gray-600 rounded-lg p-3 h-32 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-gray-200 placeholder-gray-500 resize-none" placeholder="A beautiful landscape with mountains and a lake at sunset..."></textarea> |
|
<div class="absolute bottom-2 right-2 text-xs text-gray-500"> |
|
<span id="charCount">0</span>/500 |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="grid grid-cols-2 gap-4 mb-5"> |
|
<div> |
|
<label class="block text-sm font-medium text-gray-300 mb-2">Style</label> |
|
<select class="w-full bg-gray-700 border border-gray-600 rounded-lg p-2 text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-gray-200"> |
|
<option class="bg-gray-800">Realistic</option> |
|
<option class="bg-gray-800">Digital Art</option> |
|
<option class="bg-gray-800">Watercolor</option> |
|
<option class="bg-gray-800">Pixel Art</option> |
|
<option class="bg-gray-800">Anime</option> |
|
<option class="bg-gray-800">Cyberpunk</option> |
|
<option class="bg-gray-800">Steampunk</option> |
|
</select> |
|
</div> |
|
<div> |
|
<label class="block text-sm font-medium text-gray-300 mb-2">Aspect Ratio</label> |
|
<select class="w-full bg-gray-700 border border-gray-600 rounded-lg p-2 text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-gray-200"> |
|
<option class="bg-gray-800">Square (1:1)</option> |
|
<option class="bg-gray-800">Portrait (4:5)</option> |
|
<option class="bg-gray-800">Landscape (16:9)</option> |
|
<option class="bg-gray-800">Widescreen (21:9)</option> |
|
<option class="bg-gray-800">Mobile (9:16)</option> |
|
</select> |
|
</div> |
|
</div> |
|
|
|
<div class="mb-5"> |
|
<label class="block text-sm font-medium text-gray-300 mb-2">Advanced Options</label> |
|
<div class="bg-gray-750 rounded-lg p-3"> |
|
<div class="grid grid-cols-2 gap-4"> |
|
<div class="flex items-center"> |
|
<input type="checkbox" id="highQuality" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-600 rounded bg-gray-700"> |
|
<label for="highQuality" class="ml-2 block text-sm text-gray-300">High Quality</label> |
|
</div> |
|
<div class="flex items-center"> |
|
<input type="checkbox" id="nsfwFilter" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-600 rounded bg-gray-700" checked> |
|
<label for="nsfwFilter" class="ml-2 block text-sm text-gray-300">NSFW Filter</label> |
|
</div> |
|
<div class="flex items-center"> |
|
<input type="checkbox" id="faceEnhance" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-600 rounded bg-gray-700"> |
|
<label for="faceEnhance" class="ml-2 block text-sm text-gray-300">Face Enhance</label> |
|
</div> |
|
<div class="flex items-center"> |
|
<input type="checkbox" id="upscale" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-600 rounded bg-gray-700"> |
|
<label for="upscale" class="ml-2 block text-sm text-gray-300">2x Upscale</label> |
|
</div> |
|
</div> |
|
|
|
<div class="mt-3"> |
|
<label class="block text-xs text-gray-400 mb-1">Guidance Scale</label> |
|
<input type="range" min="1" max="20" value="7" class="w-full h-2 bg-gray-600 rounded-lg appearance-none cursor-pointer"> |
|
<div class="flex justify-between text-xs text-gray-400 mt-1"> |
|
<span>More Creative</span> |
|
<span>More Precise</span> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<div class="flex justify-between items-center"> |
|
<div class="text-xs text-gray-500"> |
|
<i class="fas fa-info-circle text-blue-400 mr-1"></i> |
|
Uses ~<span id="vramEstimate">3.2</span>GB VRAM |
|
</div> |
|
<div class="flex space-x-3"> |
|
<button id="cancelPromptBtn" class="px-5 py-2 border border-gray-600 rounded-lg text-sm hover:bg-gray-700 text-gray-300 transition">Cancel</button> |
|
<button id="generateBtn" class="px-5 py-2 bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white rounded-lg text-sm flex items-center space-x-2 transition shadow-md"> |
|
<i class="fas fa-magic"></i> |
|
<span>Generate</span> |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div id="loadingOverlay" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center z-50 hidden backdrop-blur-sm"> |
|
<div class="bg-gray-800 rounded-xl p-6 max-w-md w-full text-center border border-gray-700"> |
|
<div class="animate-spin rounded-full h-16 w-16 border-b-2 border-blue-500 mx-auto mb-5"></div> |
|
<h3 class="text-lg font-medium text-white mb-1">Generating Your Image</h3> |
|
<p id="loadingText" class="text-sm text-gray-300 mb-3">Initializing model...</p> |
|
|
|
<div class="w-full bg-gray-700 rounded-full h-2.5 mb-4"> |
|
<div id="progressBar" class="bg-gradient-to-r from-blue-500 to-purple-600 h-2.5 rounded-full" style="width: 0%"></div> |
|
</div> |
|
|
|
<div class="grid grid-cols-3 gap-2 text-xs text-gray-400"> |
|
<div class="flex items-center justify-center space-x-1"> |
|
<i class="fas fa-microchip text-blue-400"></i> |
|
<span id="loadingVram">4.8/24 GB</span> |
|
</div> |
|
<div class="flex items-center justify-center space-x-1"> |
|
<i class="fas fa-bolt text-yellow-400"></i> |
|
<span id="loadingGpu">78%</span> |
|
</div> |
|
<div class="flex items-center justify-center space-x-1"> |
|
<i class="fas fa-clock text-gray-400"></i> |
|
<span id="loadingTime">~12s</span> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
|
|
<div id="notificationToast" class="fixed bottom-4 right-4 bg-gray-800 border border-gray-700 rounded-lg p-4 shadow-xl z-50 hidden transform transition-all duration-300 translate-y-2 opacity-0"> |
|
<div class="flex items-start"> |
|
<div id="toastIcon" class="flex-shrink-0"> |
|
<i class="fas fa-check-circle text-green-400 text-xl"></i> |
|
</div> |
|
<div class="ml-3"> |
|
<h3 id="toastTitle" class="text-sm font-medium text-white">Success</h3> |
|
<p id="toastMessage" class="text-sm text-gray-300 mt-1">Image generated successfully!</p> |
|
</div> |
|
<button id="closeToastBtn" class="ml-4 flex-shrink-0 text-gray-400 hover:text-gray-300"> |
|
<i class="fas fa-times"></i> |
|
</button> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
|
|
const openPromptBtn = document.getElementById('openPromptBtn'); |
|
const quickGenerateBtn = document.getElementById('quickGenerateBtn'); |
|
const closePromptBtn = document.getElementById('closePromptBtn'); |
|
const cancelPromptBtn = document.getElementById('cancelPromptBtn'); |
|
const generateBtn = document.getElementById('generateBtn'); |
|
const promptDialog = document.getElementById('promptDialog'); |
|
const loadingOverlay = document.getElementById('loadingOverlay'); |
|
const promptInput = document.getElementById('promptInput'); |
|
const imageContainer = document.getElementById('imageContainer'); |
|
const imageControls = document.getElementById('imageControls'); |
|
const charCount = document.getElementById('charCount'); |
|
const notificationToast = document.getElementById('notificationToast'); |
|
const closeToastBtn = document.getElementById('closeToastBtn'); |
|
const progressBar = document.getElementById('progressBar'); |
|
const loadingText = document.getElementById('loadingText'); |
|
const loadingVram = document.getElementById('loadingVram'); |
|
const loadingGpu = document.getElementById('loadingGpu'); |
|
const loadingTime = document.getElementById('loadingTime'); |
|
const vramEstimate = document.getElementById('vramEstimate'); |
|
|
|
|
|
function updateClock() { |
|
const now = new Date(); |
|
const timeString = now.toLocaleTimeString(); |
|
document.getElementById('currentTime').textContent = timeString; |
|
|
|
|
|
const vramUsage = document.getElementById('vramUsage'); |
|
const gpuUsage = document.getElementById('gpuUsage'); |
|
const ramUsage = document.getElementById('ramUsage'); |
|
|
|
|
|
const vramValue = (4 + Math.random() * 0.5).toFixed(1); |
|
const gpuValue = Math.floor(60 + Math.random() * 15); |
|
const ramValue = (5.5 + Math.random() * 0.5).toFixed(1); |
|
|
|
vramUsage.textContent = vramValue; |
|
gpuUsage.textContent = gpuValue; |
|
ramUsage.textContent = ramValue; |
|
} |
|
|
|
setInterval(updateClock, 1000); |
|
updateClock(); |
|
|
|
|
|
promptInput.addEventListener('input', () => { |
|
const count = promptInput.value.length; |
|
charCount.textContent = count; |
|
|
|
if (count > 500) { |
|
charCount.classList.add('text-red-400'); |
|
} else { |
|
charCount.classList.remove('text-red-400'); |
|
} |
|
|
|
|
|
const vramEst = (2.5 + (count / 500)).toFixed(1); |
|
vramEstimate.textContent = vramEst; |
|
}); |
|
|
|
|
|
function showToast(title, message, type = 'success') { |
|
const toastIcon = document.getElementById('toastIcon'); |
|
const toastTitle = document.getElementById('toastTitle'); |
|
const toastMessage = document.getElementById('toastMessage'); |
|
|
|
|
|
if (type === 'success') { |
|
toastIcon.innerHTML = '<i class="fas fa-check-circle text-green-400 text-xl"></i>'; |
|
toastTitle.classList.remove('text-red-400', 'text-yellow-400'); |
|
toastTitle.classList.add('text-white'); |
|
} else if (type === 'error') { |
|
toastIcon.innerHTML = '<i class="fas fa-exclamation-circle text-red-400 text-xl"></i>'; |
|
toastTitle.classList.remove('text-white', 'text-yellow-400'); |
|
toastTitle.classList.add('text-red-400'); |
|
} else if (type === 'warning') { |
|
toastIcon.innerHTML = '<i class="fas fa-exclamation-triangle text-yellow-400 text-xl"></i>'; |
|
toastTitle.classList.remove('text-white', 'text-red-400'); |
|
toastTitle.classList.add('text-yellow-400'); |
|
} |
|
|
|
toastTitle.textContent = title; |
|
toastMessage.textContent = message; |
|
|
|
notificationToast.classList.remove('hidden'); |
|
setTimeout(() => { |
|
notificationToast.classList.remove('translate-y-2', 'opacity-0'); |
|
notificationToast.classList.add('translate-y-0', 'opacity-100'); |
|
}, 10); |
|
|
|
|
|
setTimeout(hideToast, 5000); |
|
} |
|
|
|
|
|
function hideToast() { |
|
notificationToast.classList.add('translate-y-2', 'opacity-0'); |
|
setTimeout(() => { |
|
notificationToast.classList.add('hidden'); |
|
}, 300); |
|
} |
|
|
|
closeToastBtn.addEventListener('click', hideToast); |
|
|
|
|
|
openPromptBtn.addEventListener('click', () => { |
|
promptDialog.classList.remove('hidden'); |
|
setTimeout(() => { |
|
promptInput.focus(); |
|
}, 100); |
|
}); |
|
|
|
|
|
quickGenerateBtn.addEventListener('click', () => { |
|
const quickPrompts = [ |
|
"A futuristic cityscape at night with neon lights and flying cars", |
|
"Majestic mountain landscape with a crystal clear lake at sunrise", |
|
"Cyberpunk female warrior with glowing tattoos and high-tech armor", |
|
"Cute kitten sitting on a stack of books in a cozy library", |
|
"Surreal dreamscape with floating islands and giant jellyfish" |
|
]; |
|
|
|
const randomPrompt = quickPrompts[Math.floor(Math.random() * quickPrompts.length)]; |
|
promptInput.value = randomPrompt; |
|
promptDialog.classList.remove('hidden'); |
|
}); |
|
|
|
|
|
function closePromptDialog() { |
|
promptDialog.classList.add('hidden'); |
|
} |
|
|
|
closePromptBtn.addEventListener('click', closePromptDialog); |
|
cancelPromptBtn.addEventListener('click', closePromptDialog); |
|
|
|
|
|
generateBtn.addEventListener('click', () => { |
|
const prompt = promptInput.value.trim(); |
|
if (!prompt) { |
|
showToast('Error', 'Please enter a prompt', 'error'); |
|
return; |
|
} |
|
|
|
if (prompt.length > 500) { |
|
showToast('Warning', 'Prompt is too long (max 500 chars)', 'warning'); |
|
return; |
|
} |
|
|
|
closePromptDialog(); |
|
loadingOverlay.classList.remove('hidden'); |
|
|
|
|
|
let progress = 0; |
|
const loadingStages = [ |
|
"Initializing model...", |
|
"Processing prompt...", |
|
"Generating latent space...", |
|
"Upscaling image...", |
|
"Applying final touches..." |
|
]; |
|
|
|
const interval = setInterval(() => { |
|
progress += Math.random() * 10; |
|
if (progress > 100) progress = 100; |
|
|
|
progressBar.style.width = `${progress}%`; |
|
|
|
|
|
if (progress < 20) { |
|
loadingText.textContent = loadingStages[0]; |
|
} else if (progress < 40) { |
|
loadingText.textContent = loadingStages[1]; |
|
} else if (progress < 60) { |
|
loadingText.textContent = loadingStages[2]; |
|
} else if (progress < 80) { |
|
loadingText.textContent = loadingStages[3]; |
|
} else { |
|
loadingText.textContent = loadingStages[4]; |
|
} |
|
|
|
|
|
const vramValue = (4.5 + Math.random() * 1.5).toFixed(1); |
|
const gpuValue = Math.floor(70 + Math.random() * 25); |
|
const timeLeft = Math.floor((100 - progress) / 10); |
|
|
|
loadingVram.textContent = `${vramValue}/24 GB`; |
|
loadingGpu.textContent = `${gpuValue}%`; |
|
loadingTime.textContent = `~${timeLeft}s`; |
|
|
|
if (progress === 100) { |
|
clearInterval(interval); |
|
setTimeout(() => { |
|
loadingOverlay.classList.add('hidden'); |
|
showGeneratedImage(prompt); |
|
}, 500); |
|
} |
|
}, 300); |
|
}); |
|
|
|
|
|
function showGeneratedImage(prompt) { |
|
|
|
const mockImage = document.createElement('div'); |
|
mockImage.className = 'w-full h-full flex flex-col items-center justify-center p-6 relative'; |
|
|
|
|
|
const colors = [ |
|
'from-purple-500 via-pink-500 to-red-500', |
|
'from-blue-500 via-indigo-500 to-purple-500', |
|
'from-green-500 via-teal-500 to-blue-500', |
|
'from-yellow-500 via-orange-500 to-red-500', |
|
'from-pink-500 via-purple-500 to-indigo-500' |
|
]; |
|
const randomColor = colors[Math.floor(Math.random() * colors.length)]; |
|
|
|
mockImage.innerHTML = ` |
|
<div class="relative w-full h-full max-w-2xl"> |
|
<div class="w-full h-full bg-gradient-to-br ${randomColor} rounded-xl shadow-2xl flex items-center justify-center overflow-hidden"> |
|
<div class="absolute inset-0 flex items-center justify-center"> |
|
<div class="w-32 h-32 rounded-full bg-white bg-opacity-20 blur-xl"></div> |
|
</div> |
|
<div class="relative z-10 text-center p-6"> |
|
<i class="fas fa-image text-white text-6xl opacity-80"></i> |
|
<div class="mt-4 bg-black bg-opacity-40 rounded-lg p-3"> |
|
<p class="text-white font-medium">"${prompt}"</p> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="absolute -bottom-2 -right-2 bg-gradient-to-r from-blue-500 to-purple-600 text-white text-xs px-3 py-1 rounded-full shadow-md"> |
|
AI Generated |
|
</div> |
|
<div class="absolute top-4 left-4 flex space-x-2"> |
|
<span class="bg-gray-800 bg-opacity-80 text-white text-xs px-2 py-1 rounded">512×512</span> |
|
<span class="bg-gray-800 bg-opacity-80 text-white text-xs px-2 py-1 rounded">30 steps</span> |
|
</div> |
|
</div> |
|
<div class="mt-6 text-center max-w-md"> |
|
<p class="text-gray-300 text-sm">${getRandomArtistName()} style, ${getRandomModelName()}</p> |
|
<p class="text-gray-400 text-xs mt-2">Generated at ${new Date().toLocaleTimeString()}</p> |
|
</div> |
|
`; |
|
|
|
|
|
imageContainer.innerHTML = ''; |
|
imageContainer.appendChild(mockImage); |
|
imageControls.classList.remove('hidden'); |
|
|
|
|
|
const sidebar = document.querySelector('.bg-gray-750 .space-y-2'); |
|
const recentPrompt = document.createElement('div'); |
|
recentPrompt.className = 'group relative'; |
|
recentPrompt.innerHTML = ` |
|
<div class="p-2 text-sm hover:bg-gray-700 rounded-md cursor-pointer transition flex items-center justify-between"> |
|
<span class="truncate">${prompt}</span> |
|
<i class="fas fa-redo text-gray-500 group-hover:text-blue-400 transition ml-2"></i> |
|
</div> |
|
`; |
|
|
|
|
|
recentPrompt.querySelector('div').addEventListener('click', () => { |
|
promptInput.value = prompt; |
|
promptDialog.classList.remove('hidden'); |
|
}); |
|
|
|
sidebar.insertBefore(recentPrompt, sidebar.firstChild); |
|
|
|
|
|
if (sidebar.children.length > 5) { |
|
sidebar.removeChild(sidebar.lastChild); |
|
} |
|
|
|
|
|
showToast('Success', 'Image generated successfully!'); |
|
} |
|
|
|
|
|
function getRandomArtistName() { |
|
const artists = [ |
|
"in the style of Greg Rutkowski", |
|
"trending on ArtStation", |
|
"hyperdetailed digital painting", |
|
"cinematic lighting", |
|
"concept art", |
|
"Studio Ghibli inspired", |
|
"Blizzard Entertainment style" |
|
]; |
|
return artists[Math.floor(Math.random() * artists.length)]; |
|
} |
|
|
|
function getRandomModelName() { |
|
const models = [ |
|
"Stable Diffusion XL", |
|
"DreamShaper v7", |
|
"Realistic Vision v5", |
|
"Deliberate v2", |
|
"Protogen x5.8", |
|
"Rev Animated v1.2" |
|
]; |
|
return models[Math.floor(Math.random() * models.length)]; |
|
} |
|
|
|
|
|
document.querySelectorAll('.bg-gray-750 .space-y-2 > div').forEach((item, index) => { |
|
item.addEventListener('click', () => { |
|
const samplePrompts = [ |
|
"A majestic lion in the savanna at sunset", |
|
"Futuristic city with flying cars", |
|
"Watercolor painting of a forest in autumn", |
|
"Cyberpunk street with neon lights", |
|
"Portrait of a steampunk inventor" |
|
]; |
|
|
|
promptInput.value = samplePrompts[index] || item.textContent; |
|
promptDialog.classList.remove('hidden'); |
|
}); |
|
}); |
|
|
|
|
|
document.querySelectorAll('.grid.grid-cols-2.gap-2 > div').forEach((item, index) => { |
|
item.addEventListener('click', () => { |
|
const stylePrompts = [ |
|
"A breathtaking mountain landscape with a waterfall and sunset, highly detailed", |
|
"Professional portrait of a business person with perfect lighting, 8k resolution", |
|
"A powerful wizard casting a spell in a mystical forest, fantasy art", |
|
"Futuristic spaceship orbiting an alien planet, sci-fi concept art", |
|
"Still life painting of flowers in a vase, impressionist style", |
|
"8-bit pixel art scene of a medieval village with charming details" |
|
]; |
|
|
|
if (index < stylePrompts.length) { |
|
promptInput.value = stylePrompts[index]; |
|
promptDialog.classList.remove('hidden'); |
|
} |
|
}); |
|
}); |
|
|
|
|
|
document.querySelectorAll('.mt-6 .space-y-2 > div').forEach((item, index) => { |
|
item.addEventListener('click', () => { |
|
const quickPrompts = [ |
|
"A futuristic city at night with neon lights and rain-soaked streets, cyberpunk style", |
|
"Watercolor landscape of mountains reflected in a calm lake at sunrise", |
|
"Cyberpunk character portrait with glowing tattoos and intricate armor design" |
|
]; |
|
|
|
if (index < quickPrompts.length) { |
|
promptInput.value = quickPrompts[index]; |
|
promptDialog.classList.remove('hidden'); |
|
} |
|
}); |
|
}); |
|
</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=bennijo/displays-a-contextual-window" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
</html> |