Donmill commited on
Commit
0e4a9ab
·
verified ·
1 Parent(s): 091f235

Add 2 files

Browse files
Files changed (2) hide show
  1. index.html +153 -79
  2. prompts.txt +2 -1
index.html CHANGED
@@ -18,12 +18,6 @@
18
  aspect-ratio: 1/1;
19
  background-color: #2a2a3a;
20
  }
21
- .nsfw-toggle {
22
- transition: all 0.3s ease;
23
- }
24
- .nsfw-toggle.active {
25
- background-color: #ff4d4d;
26
- }
27
  .slider-thumb::-webkit-slider-thumb {
28
  -webkit-appearance: none;
29
  appearance: none;
@@ -50,6 +44,13 @@
50
  .history-item:hover {
51
  transform: scale(1.05);
52
  }
 
 
 
 
 
 
 
53
  </style>
54
  </head>
55
  <body class="gradient-bg text-gray-100 min-h-screen">
@@ -70,7 +71,7 @@
70
  </label>
71
  <span class="ml-2">NSFW</span>
72
  </div>
73
- <button id="settings-btn" class="p-2 rounded-full hover:bg-gray-700 transition">
74
  <i class="fas fa-cog text-xl"></i>
75
  </button>
76
  </div>
@@ -82,23 +83,23 @@
82
  <div class="space-y-6">
83
  <div>
84
  <label for="prompt" class="block text-sm font-medium mb-2">Prompt</label>
85
- <textarea id="prompt" class="w-full prompt-textarea p-4 rounded-lg bg-gray-800 border border-gray-700 focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none transition" placeholder="Describe what you want to generate..."></textarea>
86
  </div>
87
 
88
  <div>
89
  <label for="negative-prompt" class="block text-sm font-medium mb-2">Negative Prompt</label>
90
- <textarea id="negative-prompt" class="w-full prompt-textarea p-4 rounded-lg bg-gray-800 border border-gray-700 focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none transition" placeholder="What you don't want to see..."></textarea>
91
  </div>
92
 
93
  <!-- Advanced Options (Collapsible) -->
94
  <div class="bg-gray-800 rounded-lg overflow-hidden">
95
- <div id="advanced-toggle" class="flex justify-between items-center p-4 cursor-pointer">
96
  <h3 class="font-medium">Advanced Options</h3>
97
  <i id="advanced-arrow" class="fas fa-chevron-down transition-transform"></i>
98
- </div>
99
  <div id="advanced-options" class="px-4 pb-4 hidden space-y-4">
100
  <div>
101
- <label class="block text-sm font-medium mb-2">Model</label>
102
  <select id="model-select" class="w-full p-2 rounded bg-gray-700 border border-gray-600 outline-none">
103
  <option value="stabilityai/stable-diffusion-xl-base-1.0">Stable Diffusion XL</option>
104
  <option value="runwayml/stable-diffusion-v1-5">Stable Diffusion 1.5</option>
@@ -107,7 +108,7 @@
107
  </div>
108
 
109
  <div>
110
- <label class="block text-sm font-medium mb-2">Sampler</label>
111
  <select id="sampler-select" class="w-full p-2 rounded bg-gray-700 border border-gray-600 outline-none">
112
  <option value="DPMSolverMultistepScheduler">DPM++ 2M Karras</option>
113
  <option value="EulerAncestralDiscreteScheduler">Euler a</option>
@@ -117,20 +118,20 @@
117
  </div>
118
 
119
  <div>
120
- <label class="block text-sm font-medium mb-2">Steps <span id="steps-value" class="text-gray-400">20</span></label>
121
- <input id="steps-slider" type="range" min="10" max="50" value="20" class="w-full slider-thumb" oninput="updateStepsValue(this.value)">
122
  </div>
123
 
124
  <div>
125
- <label class="block text-sm font-medium mb-2">CFG Scale <span id="cfg-value" class="text-gray-400">7</span></label>
126
- <input id="cfg-slider" type="range" min="1" max="20" value="7" class="w-full slider-thumb" oninput="updateCFGValue(this.value)">
127
  </div>
128
 
129
  <div>
130
- <label class="block text-sm font-medium mb-2">Seed</label>
131
  <div class="flex space-x-2">
132
- <input id="seed-input" type="number" class="flex-1 p-2 rounded bg-gray-700 border border-gray-600 outline-none" placeholder="Random">
133
- <button onclick="randomizeSeed()" class="px-4 py-2 bg-gray-700 rounded hover:bg-gray-600 transition">Randomize</button>
134
  </div>
135
  </div>
136
  </div>
@@ -140,7 +141,7 @@
140
  <button id="generate-btn" class="flex-1 py-3 px-6 bg-gradient-to-r from-purple-600 to-pink-600 rounded-lg font-medium hover:opacity-90 transition flex items-center justify-center">
141
  <i class="fas fa-bolt mr-2"></i> Generate
142
  </button>
143
- <button onclick="randomizePrompt()" class="py-3 px-6 bg-gray-700 rounded-lg font-medium hover:bg-gray-600 transition">
144
  <i class="fas fa-random"></i>
145
  </button>
146
  </div>
@@ -153,7 +154,7 @@
153
  <i class="fas fa-image fa-3x mb-4"></i>
154
  <p>Your generated image will appear here</p>
155
  </div>
156
- <img id="generated-image" class="w-full h-full hidden object-cover" alt="Generated image">
157
  <div id="progress-overlay" class="absolute inset-0 blur-overlay hidden flex-col items-center justify-center">
158
  <div class="w-3/4 bg-gray-700 rounded-full h-2 mb-4">
159
  <div id="progress-bar" class="bg-gradient-to-r from-purple-500 to-pink-500 h-2 rounded-full" style="width: 0%"></div>
@@ -167,13 +168,13 @@
167
  <button id="download-btn" class="flex-1 py-2 px-4 bg-gray-700 rounded-lg hover:bg-gray-600 transition flex items-center justify-center">
168
  <i class="fas fa-download mr-2"></i> Download
169
  </button>
170
- <button onclick="regenerateImage()" class="flex-1 py-2 px-4 bg-gray-700 rounded-lg hover:bg-gray-600 transition flex items-center justify-center">
171
  <i class="fas fa-undo mr-2"></i> Retry
172
  </button>
173
- <button onclick="enhanceImage()" class="flex-1 py-2 px-4 bg-gray-700 rounded-lg hover:bg-gray-600 transition flex items-center justify-center">
174
  <i class="fas fa-magic mr-2"></i> Enhance
175
  </button>
176
- <button onclick="upscaleImage()" class="flex-1 py-2 px-4 bg-gray-700 rounded-lg hover:bg-gray-600 transition flex items-center justify-center">
177
  <i class="fas fa-expand mr-2"></i> Upscale
178
  </button>
179
  </div>
@@ -194,17 +195,17 @@
194
  <div class="bg-gray-800 rounded-lg w-full max-w-md max-h-[90vh] overflow-y-auto">
195
  <div class="p-4 border-b border-gray-700 flex justify-between items-center">
196
  <h3 class="text-lg font-medium">Settings</h3>
197
- <button onclick="closeSettings()" class="p-1 rounded-full hover:bg-gray-700 transition">
198
  <i class="fas fa-times"></i>
199
  </button>
200
  </div>
201
  <div class="p-4 space-y-4">
202
  <div>
203
- <label class="block text-sm font-medium mb-2">Real-time Update Delay (ms)</label>
204
  <input id="update-delay" type="number" value="1000" min="500" max="5000" step="100" class="w-full p-2 rounded bg-gray-700 border border-gray-600 outline-none">
205
  </div>
206
  <div>
207
- <label class="block text-sm font-medium mb-2">Image Resolution</label>
208
  <select id="resolution-select" class="w-full p-2 rounded bg-gray-700 border border-gray-600 outline-none">
209
  <option value="512x512">512x512</option>
210
  <option value="768x768">768x768</option>
@@ -213,7 +214,7 @@
213
  </select>
214
  </div>
215
  <div>
216
- <label class="block text-sm font-medium mb-2">NSFW Filter Strength</label>
217
  <input id="nsfw-filter" type="range" min="0" max="100" value="50" class="w-full slider-thumb">
218
  </div>
219
  <div class="pt-2">
@@ -230,14 +231,14 @@
230
  </div>
231
  </div>
232
  <div class="p-4 border-t border-gray-700 flex justify-end space-x-2">
233
- <button onclick="closeSettings()" class="px-4 py-2 bg-gray-700 rounded-lg hover:bg-gray-600 transition">Cancel</button>
234
- <button onclick="saveSettings()" class="px-4 py-2 bg-gradient-to-r from-purple-600 to-pink-600 rounded-lg hover:opacity-90 transition">Save</button>
235
  </div>
236
  </div>
237
  </div>
238
 
239
  <script>
240
- // Configuration
241
  const config = {
242
  nsfwEnabled: false,
243
  updateDelay: 1000,
@@ -246,7 +247,7 @@
246
  currentGeneration: null
247
  };
248
 
249
- // UI Elements
250
  const elements = {
251
  prompt: document.getElementById('prompt'),
252
  negativePrompt: document.getElementById('negative-prompt'),
@@ -261,12 +262,58 @@
261
  nsfwToggle: document.getElementById('nsfw-toggle'),
262
  advancedToggle: document.getElementById('advanced-toggle'),
263
  advancedOptions: document.getElementById('advanced-options'),
264
- advancedArrow: document.getElementById('advanced-arrow')
 
 
 
 
 
 
 
 
 
 
265
  };
266
 
267
- // Initialize
268
- document.addEventListener('DOMContentLoaded', () => {
269
- // Load settings from localStorage
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  if (localStorage.getItem('updateDelay')) {
271
  config.updateDelay = parseInt(localStorage.getItem('updateDelay'));
272
  }
@@ -278,57 +325,92 @@
278
  elements.nsfwToggle.checked = config.nsfwEnabled;
279
  }
280
 
281
- // Load history if exists
282
  if (localStorage.getItem('history')) {
283
- config.history = JSON.parse(localStorage.getItem('history'));
284
- renderHistory();
 
 
 
 
285
  }
286
-
287
- // Set up event listeners
288
- setupEventListeners();
289
- });
290
 
 
291
  function setupEventListeners() {
292
  // NSFW toggle
293
  elements.nsfwToggle.addEventListener('change', function() {
294
  config.nsfwEnabled = this.checked;
295
  localStorage.setItem('nsfwEnabled', this.checked);
296
- console.log('NSFW mode:', this.checked ? 'ON' : 'OFF');
297
  });
298
 
299
  // Advanced options toggle
300
  elements.advancedToggle.addEventListener('click', toggleAdvancedOptions);
301
 
302
- // Prompt typing
303
- let typingTimer;
304
- elements.prompt.addEventListener('input', () => {
305
- clearTimeout(typingTimer);
306
  if (elements.prompt.value) {
307
- typingTimer = setTimeout(generateImage, config.updateDelay);
308
  }
309
- });
310
 
311
  // Generate button
312
- elements.generateBtn.addEventListener('click', generateImage);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  }
314
 
315
  // UI Toggles
316
  function toggleAdvancedOptions() {
317
- elements.advancedOptions.classList.toggle('hidden');
318
  elements.advancedArrow.classList.toggle('rotate-180');
 
319
  }
320
 
321
  // Settings Modal
322
- document.getElementById('settings-btn').addEventListener('click', () => {
323
- document.getElementById('settings-modal').classList.remove('hidden');
324
  document.getElementById('update-delay').value = config.updateDelay;
325
  document.getElementById('resolution-select').value = config.resolution;
326
  document.getElementById('save-history').checked = localStorage.getItem('saveHistory') !== 'false';
327
  document.getElementById('show-progress').checked = localStorage.getItem('showProgress') !== 'false';
328
- });
 
329
 
330
  function closeSettings() {
331
- document.getElementById('settings-modal').classList.add('hidden');
332
  }
333
 
334
  function saveSettings() {
@@ -341,15 +423,7 @@
341
  closeSettings();
342
  }
343
 
344
- // Slider value updates
345
- function updateStepsValue(value) {
346
- document.getElementById('steps-value').textContent = value;
347
- }
348
-
349
- function updateCFGValue(value) {
350
- document.getElementById('cfg-value').textContent = value;
351
- }
352
-
353
  function randomizeSeed() {
354
  const seed = Math.floor(Math.random() * 1000000);
355
  document.getElementById('seed-input').value = seed;
@@ -376,8 +450,6 @@
376
  }
377
 
378
  // Image Generation
379
- let lastGenerationTime = 0;
380
-
381
  async function generateImage() {
382
  const prompt = elements.prompt.value;
383
  if (!prompt) return;
@@ -389,6 +461,11 @@
389
  }
390
  lastGenerationTime = now;
391
 
 
 
 
 
 
392
  // Show loading state
393
  elements.imagePlaceholder.classList.add('hidden');
394
  elements.generatedImage.classList.add('hidden');
@@ -410,7 +487,7 @@
410
  try {
411
  // Simulate progress
412
  let progress = 0;
413
- const interval = setInterval(() => {
414
  progress += Math.random() * 10;
415
  if (progress > 100) progress = 100;
416
  elements.progressBar.style.width = `${progress}%`;
@@ -426,7 +503,7 @@
426
  }
427
 
428
  if (progress === 100) {
429
- clearInterval(interval);
430
  }
431
  }, 200);
432
 
@@ -436,14 +513,11 @@
436
  // Display the generated image
437
  elements.generatedImage.src = imageUrl;
438
  elements.generatedImage.onload = () => {
439
- clearInterval(interval);
440
  elements.progressOverlay.classList.add('hidden');
441
  elements.generatedImage.classList.remove('hidden');
442
  elements.generatedImage.classList.add('fade-in');
443
 
444
- // Enable download button
445
- elements.downloadBtn.onclick = () => downloadImage(imageUrl, `ai-image-${Date.now()}.png`);
446
-
447
  // Add to history if enabled
448
  if (localStorage.getItem('saveHistory') !== 'false') {
449
  addToHistory(imageUrl, prompt);
@@ -476,9 +550,6 @@
476
 
477
  // Get placeholder image based on prompt
478
  async function getPlaceholderImage(prompt, isNSFW) {
479
- // In a real implementation, this would call an actual AI API
480
- // For demo purposes, we return different placeholder images based on the prompt
481
-
482
  // Create a simple hash from the prompt to determine which image to show
483
  let hash = 0;
484
  for (let i = 0; i < prompt.length; i++) {
@@ -565,9 +636,9 @@
565
 
566
  config.history.forEach((item, index) => {
567
  const historyItem = document.createElement('div');
568
- historyItem.className = 'history-item rounded overflow-hidden cursor-pointer';
569
  historyItem.innerHTML = `
570
- <img src="${item.imageUrl}" alt="History image ${index}" class="w-full h-full object-cover aspect-square">
571
  <div class="absolute inset-0 bg-black bg-opacity-50 opacity-0 hover:opacity-100 transition-opacity flex items-center justify-center p-2 text-xs">
572
  ${item.prompt.substring(0, 30)}${item.prompt.length > 30 ? '...' : ''}
573
  </div>
@@ -592,6 +663,9 @@
592
  a.click();
593
  document.body.removeChild(a);
594
  }
 
 
 
595
  </script>
596
  <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=Donmill/real-time-magic" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
597
  </html>
 
18
  aspect-ratio: 1/1;
19
  background-color: #2a2a3a;
20
  }
 
 
 
 
 
 
21
  .slider-thumb::-webkit-slider-thumb {
22
  -webkit-appearance: none;
23
  appearance: none;
 
44
  .history-item:hover {
45
  transform: scale(1.05);
46
  }
47
+ /* Optimized animations */
48
+ @media (prefers-reduced-motion: reduce) {
49
+ .fade-in, .history-item {
50
+ animation: none !important;
51
+ transition: none !important;
52
+ }
53
+ }
54
  </style>
55
  </head>
56
  <body class="gradient-bg text-gray-100 min-h-screen">
 
71
  </label>
72
  <span class="ml-2">NSFW</span>
73
  </div>
74
+ <button id="settings-btn" class="p-2 rounded-full hover:bg-gray-700 transition" aria-label="Settings">
75
  <i class="fas fa-cog text-xl"></i>
76
  </button>
77
  </div>
 
83
  <div class="space-y-6">
84
  <div>
85
  <label for="prompt" class="block text-sm font-medium mb-2">Prompt</label>
86
+ <textarea id="prompt" class="w-full prompt-textarea p-4 rounded-lg bg-gray-800 border border-gray-700 focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none transition" placeholder="Describe what you want to generate..." aria-label="Image description prompt"></textarea>
87
  </div>
88
 
89
  <div>
90
  <label for="negative-prompt" class="block text-sm font-medium mb-2">Negative Prompt</label>
91
+ <textarea id="negative-prompt" class="w-full prompt-textarea p-4 rounded-lg bg-gray-800 border border-gray-700 focus:border-purple-500 focus:ring-1 focus:ring-purple-500 outline-none transition" placeholder="What you don't want to see..." aria-label="Negative image description"></textarea>
92
  </div>
93
 
94
  <!-- Advanced Options (Collapsible) -->
95
  <div class="bg-gray-800 rounded-lg overflow-hidden">
96
+ <button id="advanced-toggle" class="flex justify-between items-center p-4 cursor-pointer w-full text-left" aria-expanded="false" aria-controls="advanced-options">
97
  <h3 class="font-medium">Advanced Options</h3>
98
  <i id="advanced-arrow" class="fas fa-chevron-down transition-transform"></i>
99
+ </button>
100
  <div id="advanced-options" class="px-4 pb-4 hidden space-y-4">
101
  <div>
102
+ <label for="model-select" class="block text-sm font-medium mb-2">Model</label>
103
  <select id="model-select" class="w-full p-2 rounded bg-gray-700 border border-gray-600 outline-none">
104
  <option value="stabilityai/stable-diffusion-xl-base-1.0">Stable Diffusion XL</option>
105
  <option value="runwayml/stable-diffusion-v1-5">Stable Diffusion 1.5</option>
 
108
  </div>
109
 
110
  <div>
111
+ <label for="sampler-select" class="block text-sm font-medium mb-2">Sampler</label>
112
  <select id="sampler-select" class="w-full p-2 rounded bg-gray-700 border border-gray-600 outline-none">
113
  <option value="DPMSolverMultistepScheduler">DPM++ 2M Karras</option>
114
  <option value="EulerAncestralDiscreteScheduler">Euler a</option>
 
118
  </div>
119
 
120
  <div>
121
+ <label for="steps-slider" class="block text-sm font-medium mb-2">Steps <span id="steps-value" class="text-gray-400">20</span></label>
122
+ <input id="steps-slider" type="range" min="10" max="50" value="20" class="w-full slider-thumb" aria-labelledby="steps-value">
123
  </div>
124
 
125
  <div>
126
+ <label for="cfg-slider" class="block text-sm font-medium mb-2">CFG Scale <span id="cfg-value" class="text-gray-400">7</span></label>
127
+ <input id="cfg-slider" type="range" min="1" max="20" value="7" class="w-full slider-thumb" aria-labelledby="cfg-value">
128
  </div>
129
 
130
  <div>
131
+ <label for="seed-input" class="block text-sm font-medium mb-2">Seed</label>
132
  <div class="flex space-x-2">
133
+ <input id="seed-input" type="number" class="flex-1 p-2 rounded bg-gray-700 border border-gray-600 outline-none" placeholder="Random" aria-label="Seed value">
134
+ <button id="randomize-seed" class="px-4 py-2 bg-gray-700 rounded hover:bg-gray-600 transition">Randomize</button>
135
  </div>
136
  </div>
137
  </div>
 
141
  <button id="generate-btn" class="flex-1 py-3 px-6 bg-gradient-to-r from-purple-600 to-pink-600 rounded-lg font-medium hover:opacity-90 transition flex items-center justify-center">
142
  <i class="fas fa-bolt mr-2"></i> Generate
143
  </button>
144
+ <button id="random-prompt" class="py-3 px-6 bg-gray-700 rounded-lg font-medium hover:bg-gray-600 transition" aria-label="Random prompt">
145
  <i class="fas fa-random"></i>
146
  </button>
147
  </div>
 
154
  <i class="fas fa-image fa-3x mb-4"></i>
155
  <p>Your generated image will appear here</p>
156
  </div>
157
+ <img id="generated-image" class="w-full h-full hidden object-cover" alt="Generated image" loading="lazy">
158
  <div id="progress-overlay" class="absolute inset-0 blur-overlay hidden flex-col items-center justify-center">
159
  <div class="w-3/4 bg-gray-700 rounded-full h-2 mb-4">
160
  <div id="progress-bar" class="bg-gradient-to-r from-purple-500 to-pink-500 h-2 rounded-full" style="width: 0%"></div>
 
168
  <button id="download-btn" class="flex-1 py-2 px-4 bg-gray-700 rounded-lg hover:bg-gray-600 transition flex items-center justify-center">
169
  <i class="fas fa-download mr-2"></i> Download
170
  </button>
171
+ <button id="retry-btn" class="flex-1 py-2 px-4 bg-gray-700 rounded-lg hover:bg-gray-600 transition flex items-center justify-center">
172
  <i class="fas fa-undo mr-2"></i> Retry
173
  </button>
174
+ <button id="enhance-btn" class="flex-1 py-2 px-4 bg-gray-700 rounded-lg hover:bg-gray-600 transition flex items-center justify-center">
175
  <i class="fas fa-magic mr-2"></i> Enhance
176
  </button>
177
+ <button id="upscale-btn" class="flex-1 py-2 px-4 bg-gray-700 rounded-lg hover:bg-gray-600 transition flex items-center justify-center">
178
  <i class="fas fa-expand mr-2"></i> Upscale
179
  </button>
180
  </div>
 
195
  <div class="bg-gray-800 rounded-lg w-full max-w-md max-h-[90vh] overflow-y-auto">
196
  <div class="p-4 border-b border-gray-700 flex justify-between items-center">
197
  <h3 class="text-lg font-medium">Settings</h3>
198
+ <button id="close-settings" class="p-1 rounded-full hover:bg-gray-700 transition" aria-label="Close settings">
199
  <i class="fas fa-times"></i>
200
  </button>
201
  </div>
202
  <div class="p-4 space-y-4">
203
  <div>
204
+ <label for="update-delay" class="block text-sm font-medium mb-2">Real-time Update Delay (ms)</label>
205
  <input id="update-delay" type="number" value="1000" min="500" max="5000" step="100" class="w-full p-2 rounded bg-gray-700 border border-gray-600 outline-none">
206
  </div>
207
  <div>
208
+ <label for="resolution-select" class="block text-sm font-medium mb-2">Image Resolution</label>
209
  <select id="resolution-select" class="w-full p-2 rounded bg-gray-700 border border-gray-600 outline-none">
210
  <option value="512x512">512x512</option>
211
  <option value="768x768">768x768</option>
 
214
  </select>
215
  </div>
216
  <div>
217
+ <label for="nsfw-filter" class="block text-sm font-medium mb-2">NSFW Filter Strength</label>
218
  <input id="nsfw-filter" type="range" min="0" max="100" value="50" class="w-full slider-thumb">
219
  </div>
220
  <div class="pt-2">
 
231
  </div>
232
  </div>
233
  <div class="p-4 border-t border-gray-700 flex justify-end space-x-2">
234
+ <button id="cancel-settings" class="px-4 py-2 bg-gray-700 rounded-lg hover:bg-gray-600 transition">Cancel</button>
235
+ <button id="save-settings" class="px-4 py-2 bg-gradient-to-r from-purple-600 to-pink-600 rounded-lg hover:opacity-90 transition">Save</button>
236
  </div>
237
  </div>
238
  </div>
239
 
240
  <script>
241
+ // Configuration - Using const for immutable values
242
  const config = {
243
  nsfwEnabled: false,
244
  updateDelay: 1000,
 
247
  currentGeneration: null
248
  };
249
 
250
+ // Cache DOM elements
251
  const elements = {
252
  prompt: document.getElementById('prompt'),
253
  negativePrompt: document.getElementById('negative-prompt'),
 
262
  nsfwToggle: document.getElementById('nsfw-toggle'),
263
  advancedToggle: document.getElementById('advanced-toggle'),
264
  advancedOptions: document.getElementById('advanced-options'),
265
+ advancedArrow: document.getElementById('advanced-arrow'),
266
+ randomPromptBtn: document.getElementById('random-prompt'),
267
+ randomizeSeedBtn: document.getElementById('randomize-seed'),
268
+ retryBtn: document.getElementById('retry-btn'),
269
+ enhanceBtn: document.getElementById('enhance-btn'),
270
+ upscaleBtn: document.getElementById('upscale-btn'),
271
+ settingsBtn: document.getElementById('settings-btn'),
272
+ closeSettingsBtn: document.getElementById('close-settings'),
273
+ cancelSettingsBtn: document.getElementById('cancel-settings'),
274
+ saveSettingsBtn: document.getElementById('save-settings'),
275
+ settingsModal: document.getElementById('settings-modal')
276
  };
277
 
278
+ // Initialize with throttled functions
279
+ let lastGenerationTime = 0;
280
+ let typingTimer;
281
+ let progressInterval;
282
+
283
+ // Debounce function for better performance
284
+ function debounce(func, wait) {
285
+ let timeout;
286
+ return function() {
287
+ const context = this;
288
+ const args = arguments;
289
+ clearTimeout(timeout);
290
+ timeout = setTimeout(() => func.apply(context, args), wait);
291
+ };
292
+ }
293
+
294
+ // Throttle function for rate limiting
295
+ function throttle(func, limit) {
296
+ let inThrottle;
297
+ return function() {
298
+ const args = arguments;
299
+ const context = this;
300
+ if (!inThrottle) {
301
+ func.apply(context, args);
302
+ inThrottle = true;
303
+ setTimeout(() => inThrottle = false, limit);
304
+ }
305
+ };
306
+ }
307
+
308
+ // Initialize the application
309
+ function init() {
310
+ loadSettings();
311
+ setupEventListeners();
312
+ renderHistory();
313
+ }
314
+
315
+ // Load settings from localStorage
316
+ function loadSettings() {
317
  if (localStorage.getItem('updateDelay')) {
318
  config.updateDelay = parseInt(localStorage.getItem('updateDelay'));
319
  }
 
325
  elements.nsfwToggle.checked = config.nsfwEnabled;
326
  }
327
 
 
328
  if (localStorage.getItem('history')) {
329
+ try {
330
+ config.history = JSON.parse(localStorage.getItem('history')) || [];
331
+ } catch (e) {
332
+ console.error("Error parsing history:", e);
333
+ config.history = [];
334
+ }
335
  }
336
+ }
 
 
 
337
 
338
+ // Set up event listeners
339
  function setupEventListeners() {
340
  // NSFW toggle
341
  elements.nsfwToggle.addEventListener('change', function() {
342
  config.nsfwEnabled = this.checked;
343
  localStorage.setItem('nsfwEnabled', this.checked);
 
344
  });
345
 
346
  // Advanced options toggle
347
  elements.advancedToggle.addEventListener('click', toggleAdvancedOptions);
348
 
349
+ // Prompt typing with debounce
350
+ elements.prompt.addEventListener('input', debounce(() => {
 
 
351
  if (elements.prompt.value) {
352
+ generateImage();
353
  }
354
+ }, config.updateDelay));
355
 
356
  // Generate button
357
+ elements.generateBtn.addEventListener('click', throttle(generateImage, 1000));
358
+
359
+ // Random prompt button
360
+ elements.randomPromptBtn.addEventListener('click', randomizePrompt);
361
+
362
+ // Randomize seed button
363
+ elements.randomizeSeedBtn.addEventListener('click', randomizeSeed);
364
+
365
+ // Image action buttons
366
+ elements.retryBtn.addEventListener('click', regenerateImage);
367
+ elements.enhanceBtn.addEventListener('click', enhanceImage);
368
+ elements.upscaleBtn.addEventListener('click', upscaleImage);
369
+
370
+ // Settings modal buttons
371
+ elements.settingsBtn.addEventListener('click', openSettings);
372
+ elements.closeSettingsBtn.addEventListener('click', closeSettings);
373
+ elements.cancelSettingsBtn.addEventListener('click', closeSettings);
374
+ elements.saveSettingsBtn.addEventListener('click', saveSettings);
375
+
376
+ // Slider inputs
377
+ elements.stepsSlider = document.getElementById('steps-slider');
378
+ elements.cfgSlider = document.getElementById('cfg-slider');
379
+
380
+ elements.stepsSlider.addEventListener('input', () => {
381
+ document.getElementById('steps-value').textContent = elements.stepsSlider.value;
382
+ });
383
+
384
+ elements.cfgSlider.addEventListener('input', () => {
385
+ document.getElementById('cfg-value').textContent = elements.cfgSlider.value;
386
+ });
387
+
388
+ // Download button
389
+ elements.downloadBtn.addEventListener('click', () => {
390
+ if (config.currentGeneration?.imageUrl) {
391
+ downloadImage(config.currentGeneration.imageUrl, `ai-image-${Date.now()}.png`);
392
+ }
393
+ });
394
  }
395
 
396
  // UI Toggles
397
  function toggleAdvancedOptions() {
398
+ const isExpanded = elements.advancedOptions.classList.toggle('hidden');
399
  elements.advancedArrow.classList.toggle('rotate-180');
400
+ elements.advancedToggle.setAttribute('aria-expanded', !isExpanded);
401
  }
402
 
403
  // Settings Modal
404
+ function openSettings() {
 
405
  document.getElementById('update-delay').value = config.updateDelay;
406
  document.getElementById('resolution-select').value = config.resolution;
407
  document.getElementById('save-history').checked = localStorage.getItem('saveHistory') !== 'false';
408
  document.getElementById('show-progress').checked = localStorage.getItem('showProgress') !== 'false';
409
+ elements.settingsModal.classList.remove('hidden');
410
+ }
411
 
412
  function closeSettings() {
413
+ elements.settingsModal.classList.add('hidden');
414
  }
415
 
416
  function saveSettings() {
 
423
  closeSettings();
424
  }
425
 
426
+ // Randomization functions
 
 
 
 
 
 
 
 
427
  function randomizeSeed() {
428
  const seed = Math.floor(Math.random() * 1000000);
429
  document.getElementById('seed-input').value = seed;
 
450
  }
451
 
452
  // Image Generation
 
 
453
  async function generateImage() {
454
  const prompt = elements.prompt.value;
455
  if (!prompt) return;
 
461
  }
462
  lastGenerationTime = now;
463
 
464
+ // Clear any existing progress interval
465
+ if (progressInterval) {
466
+ clearInterval(progressInterval);
467
+ }
468
+
469
  // Show loading state
470
  elements.imagePlaceholder.classList.add('hidden');
471
  elements.generatedImage.classList.add('hidden');
 
487
  try {
488
  // Simulate progress
489
  let progress = 0;
490
+ progressInterval = setInterval(() => {
491
  progress += Math.random() * 10;
492
  if (progress > 100) progress = 100;
493
  elements.progressBar.style.width = `${progress}%`;
 
503
  }
504
 
505
  if (progress === 100) {
506
+ clearInterval(progressInterval);
507
  }
508
  }, 200);
509
 
 
513
  // Display the generated image
514
  elements.generatedImage.src = imageUrl;
515
  elements.generatedImage.onload = () => {
516
+ clearInterval(progressInterval);
517
  elements.progressOverlay.classList.add('hidden');
518
  elements.generatedImage.classList.remove('hidden');
519
  elements.generatedImage.classList.add('fade-in');
520
 
 
 
 
521
  // Add to history if enabled
522
  if (localStorage.getItem('saveHistory') !== 'false') {
523
  addToHistory(imageUrl, prompt);
 
550
 
551
  // Get placeholder image based on prompt
552
  async function getPlaceholderImage(prompt, isNSFW) {
 
 
 
553
  // Create a simple hash from the prompt to determine which image to show
554
  let hash = 0;
555
  for (let i = 0; i < prompt.length; i++) {
 
636
 
637
  config.history.forEach((item, index) => {
638
  const historyItem = document.createElement('div');
639
+ historyItem.className = 'history-item rounded overflow-hidden cursor-pointer relative';
640
  historyItem.innerHTML = `
641
+ <img src="${item.imageUrl}" alt="History image ${index}" class="w-full h-full object-cover aspect-square" loading="lazy">
642
  <div class="absolute inset-0 bg-black bg-opacity-50 opacity-0 hover:opacity-100 transition-opacity flex items-center justify-center p-2 text-xs">
643
  ${item.prompt.substring(0, 30)}${item.prompt.length > 30 ? '...' : ''}
644
  </div>
 
663
  a.click();
664
  document.body.removeChild(a);
665
  }
666
+
667
+ // Initialize the app when DOM is loaded
668
+ document.addEventListener('DOMContentLoaded', init);
669
  </script>
670
  <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=Donmill/real-time-magic" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
671
  </html>
prompts.txt CHANGED
@@ -1,4 +1,5 @@
1
  A fully functional, feature packed, highly customizable, instruction following AI highly NSFW real-time text to image generator that generates images in real time as the user types by continuously sending updated prompts to the AI as the user types creating a feedback loop for greater control over generation
2
  Actually load and use an AI model for generation
3
  Fix the NSFW toggle and actually generate images
4
- Fix the issues with the 'advanced options' not opening
 
 
1
  A fully functional, feature packed, highly customizable, instruction following AI highly NSFW real-time text to image generator that generates images in real time as the user types by continuously sending updated prompts to the AI as the user types creating a feedback loop for greater control over generation
2
  Actually load and use an AI model for generation
3
  Fix the NSFW toggle and actually generate images
4
+ Fix the issues with the 'advanced options' not opening
5
+ Scan the code and check for any issues and errors and optimize it for performance