Elias207 commited on
Commit
decfe4f
·
verified ·
1 Parent(s): a321c29

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +164 -67
index.html CHANGED
@@ -183,7 +183,7 @@
183
  .loading-text { font-weight: 500; color: var(--text-secondary); }
184
  #result-grid { display: none; grid-template-columns: repeat(2, 1fr); gap: 1.5rem; width: 100%; }
185
  #result-container.has-content #result-grid { display: grid; }
186
- #result-grid img { width: 100%; aspect-ratio: 1/1; object-fit: cover; border-radius: var(--radius-input); cursor: pointer; transition: var(--transition-smooth); box-shadow: var(--shadow-md); border: 1px solid var(--panel-border); }
187
  #result-grid img:hover { transform: scale(1.05); box-shadow: var(--shadow-lg); z-index: 10; position: relative; }
188
  #error-message { color: var(--danger-color); text-align: center; margin-top: 1rem; display: none; font-weight: 500; }
189
 
@@ -200,7 +200,7 @@
200
  }
201
 
202
  #history-grid:empty::before { content: 'هنوز تصویری خلق نکرده‌اید. اولین ویرایش شما اینجا ذخیره خواهد شد.'; color: var(--text-secondary); grid-column: 1 / -1; text-align: center; padding: 3rem 1rem; background-color: var(--input-bg); border-radius: var(--radius-card); }
203
- .history-item { position: relative; background-color: var(--input-bg); border-radius: var(--radius-card); border: 1px solid var(--panel-border); padding: 1rem; transition: var(--transition-smooth); } /* Adjusted padding */
204
  .history-item:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); }
205
 
206
  .history-item-grid {
@@ -224,9 +224,8 @@
224
  #lightbox-close { top: -50px; right: 0; }
225
  #lightbox-download { top: -50px; left: 0; }
226
 
227
- /* --- CHANGE: Added Next button --- */
228
  #lightbox-next {
229
- right: -60px; /* Positioned outside the image */
230
  top: 50%;
231
  transform: translateY(-50%);
232
  }
@@ -319,7 +318,6 @@
319
  <svg fill="white" viewBox="0 0 24 24"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>
320
  <div class="spinner"></div>
321
  </button>
322
- <!-- --- CHANGE: Added Next button --- -->
323
  <button id="lightbox-next" title="بعدی" class="lightbox-btn">
324
  <svg fill="white" viewBox="0 0 24 24" width="24" height="24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6-6-6z"/></svg>
325
  </button>
@@ -327,31 +325,32 @@
327
  </div>
328
 
329
  <script>
 
330
  const API_URL = 'https://alfa-editor-worker.onrender.com/api/edit';
331
-
332
  const uploadArea = document.getElementById('upload-area');
333
  const fileInput = document.getElementById('file-input');
334
  const previewImage = document.getElementById('preview-image-main');
335
  const removeFileBtn = document.getElementById('remove-file-btn-main');
336
-
337
  const promptInput = document.getElementById('prompt-input');
338
  const submitBtn = document.getElementById('submit-btn');
339
  const resultContainer = document.getElementById('result-container');
340
  const resultGrid = document.getElementById('result-grid');
 
341
  const lightbox = document.getElementById('lightbox');
342
  const lightboxImg = document.getElementById('lightbox-img');
343
  const lightboxClose = document.getElementById('lightbox-close');
344
  const lightboxDownload = document.getElementById('lightbox-download');
345
- const lightboxNext = document.getElementById('lightbox-next'); // New button
346
  const historyGrid = document.getElementById('history-grid');
347
  const clearHistoryBtn = document.getElementById('clear-history-btn');
348
 
 
349
  let uploadedFile = null;
350
  let currentLightboxUrl = null;
351
- // --- CHANGE: Added state for lightbox navigation ---
352
  let currentLightboxGroup = [];
353
  let currentLightboxIndex = 0;
354
 
 
355
  const resetUploader = () => {
356
  uploadedFile = null;
357
  fileInput.value = '';
@@ -361,7 +360,10 @@
361
  };
362
 
363
  const handleFile = (file) => {
364
- if (!file || !file.type.startsWith('image/')) { displayError('لطفا یک فایل تصویری معتبر انتخاب کنید.'); return; }
 
 
 
365
  uploadedFile = file;
366
  const reader = new FileReader();
367
  reader.onload = (e) => { previewImage.src = e.target.result; };
@@ -371,71 +373,130 @@
371
  clearResult();
372
  };
373
 
374
- removeFileBtn.addEventListener('click', (e) => {
375
- e.preventDefault();
376
- e.stopPropagation();
377
- resetUploader();
378
- });
379
 
380
- fileInput.addEventListener('change', (e) => handleFile(e.target.files[0]));
381
- ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(e => uploadArea.addEventListener(e, p => { p.preventDefault(); p.stopPropagation(); }));
382
- ['dragenter', 'dragover'].forEach(e => uploadArea.addEventListener(e, () => { if (!uploadArea.classList.contains('has-file')) uploadArea.classList.add('drag-over'); }));
383
- ['dragleave', 'drop'].forEach(e => uploadArea.addEventListener(e, () => uploadArea.classList.remove('drag-over')));
384
- uploadArea.addEventListener('drop', e => { if (!uploadArea.classList.contains('has-file')) handleFile(e.dataTransfer.files[0]); });
385
-
386
- function checkFormState() { submitBtn.disabled = !uploadedFile || promptInput.value.trim() === ''; }
387
- submitBtn.addEventListener('click', async () => { /* ... (no changes in this function) ... */ });
 
 
 
 
 
 
 
 
 
 
388
 
389
- function displayResult(imageUrls) {
390
  resultGrid.innerHTML = '';
391
  imageUrls.forEach((url) => {
392
  const img = document.createElement('img');
393
  img.src = url;
394
  img.alt = 'تصویر ویرایش شده';
395
- // --- CHANGE: Pass the whole group of URLs for navigation ---
396
  img.addEventListener('click', () => openLightbox(url, imageUrls));
397
  resultGrid.appendChild(img);
398
  });
399
  resultContainer.classList.add('has-content');
400
- }
401
 
402
- // --- CHANGE: Lightbox functions now handle navigation ---
403
- function updateLightboxImage() {
 
 
 
 
 
 
 
 
 
 
404
  const newUrl = currentLightboxGroup[currentLightboxIndex];
405
  lightboxImg.src = newUrl;
406
- currentLightboxUrl = newUrl; // Keep this for the download function
407
- }
408
 
409
- function openLightbox(clickedUrl, urlGroup) {
410
  currentLightboxGroup = urlGroup;
411
  currentLightboxIndex = urlGroup.indexOf(clickedUrl);
412
  updateLightboxImage();
413
  lightboxNext.style.display = urlGroup.length > 1 ? 'flex' : 'none';
414
  lightbox.classList.add('visible');
415
- }
416
 
417
- function closeLightbox() {
418
  lightbox.classList.remove('visible');
419
- currentLightboxGroup = []; // Reset the group
420
- }
421
-
422
- lightboxNext.addEventListener('click', () => {
423
- currentLightboxIndex = (currentLightboxIndex + 1) % currentLightboxGroup.length;
424
- updateLightboxImage();
425
- });
426
 
427
- async function handleDownload() { /* ... (no changes in this function) ... */ }
428
-
429
- function renderHistory() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
  const history = getHistory();
431
  historyGrid.innerHTML = '';
432
  clearHistoryBtn.style.display = history.length > 0 ? 'flex' : 'none';
433
-
434
  history.forEach((item, index) => {
435
  const card = document.createElement('div');
436
  card.className = 'history-item';
437
 
438
- // --- CHANGE: Programmatically create elements to attach listeners correctly ---
439
  const deleteBtn = document.createElement('button');
440
  deleteBtn.className = 'history-delete-btn';
441
  deleteBtn.title = 'حذف این مورد';
@@ -445,12 +506,10 @@
445
 
446
  const imageGrid = document.createElement('div');
447
  imageGrid.className = 'history-item-grid';
448
-
449
  item.urls.forEach(url => {
450
  const img = document.createElement('img');
451
  img.src = url;
452
  img.alt = 'تصویر از تاریخچه';
453
- // Add listener for lightbox with navigation context
454
  img.addEventListener('click', () => openLightbox(url, item.urls));
455
  imageGrid.appendChild(img);
456
  });
@@ -458,32 +517,70 @@
458
  card.appendChild(imageGrid);
459
  historyGrid.appendChild(card);
460
  });
461
- }
462
-
463
- // Minor change to handleDeleteItem to avoid needing data-attributes
464
- const handleDeleteItem = (index) => {
465
- let history = getHistory();
466
- history.splice(index, 1);
467
- saveHistory(history);
468
  };
469
 
470
- // All other functions (API calls, loading states, etc.) remain unchanged.
471
- const getHistory = () => JSON.parse(localStorage.getItem('aiPhotoshopHistory') || '[]');
472
- const saveHistory = (history) => { localStorage.setItem('aiPhotoshopHistory', JSON.stringify(history)); renderHistory(); };
473
- const addToHistory = (item) => { let history = getHistory(); history.unshift(item); if (history.length > 15) history.pop(); saveHistory(history); };
474
- const handleClearHistory = () => { if (confirm('آیا از پاک کردن تمام تاریخچه مطمئن هستید؟')) { saveHistory([]); } };
475
- const setLoading = (isLoading) => { const btnSpinner = submitBtn.querySelector('.spinner'); const btnText = document.getElementById('btn-text'); if (isLoading) { resultContainer.classList.remove('has-content'); resultContainer.classList.add('loading'); btnSpinner.style.display = 'inline-block'; btnText.textContent = 'در حال پردازش...'; submitBtn.disabled = true; resultGrid.innerHTML = ''; document.getElementById('error-message').style.display = 'none'; } else { resultContainer.classList.remove('loading'); btnSpinner.style.display = 'none'; btnText.textContent = 'خلق کن'; checkFormState(); } };
476
- const clearResult = () => { resultGrid.innerHTML = ''; document.getElementById('error-message').style.display = 'none'; resultContainer.classList.remove('has-content'); };
477
- const displayError = (message) => { const errorMessage = document.getElementById('error-message'); errorMessage.textContent = message; errorMessage.style.display = 'block'; };
478
- submitBtn.addEventListener('click', async () => { if (submitBtn.disabled) return; setLoading(true); const formData = new FormData(); formData.append('image', uploadedFile); formData.append('prompt', promptInput.value.trim()); try { const response = await fetch(API_URL, { method: 'POST', body: formData }); if (!response.ok) { const errorData = await response.json().catch(() => ({ error: `خطای سرور: ${response.statusText}` })); throw new Error(errorData.error || `یک خطای ناشناخته رخ داد.`); } const result = await response.json(); if (result.image_urls && Array.isArray(result.image_urls) && result.image_urls.length > 0) { displayResult(result.image_urls); addToHistory({ prompt: promptInput.value.trim(), urls: result.image_urls }); } else { throw new Error('پاسخ معتبری از سرور دریافت نشد.'); } } catch (error) { displayError(error.message); } finally { setLoading(false); } });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  lightboxClose.addEventListener('click', closeLightbox);
480
  lightbox.addEventListener('click', (e) => { if (e.target === lightbox) closeLightbox(); });
481
  lightboxDownload.addEventListener('click', handleDownload);
 
 
 
 
482
  clearHistoryBtn.addEventListener('click', handleClearHistory);
483
- document.addEventListener('DOMContentLoaded', () => { renderHistory(); checkFormState(); });
484
-
485
- // This function is copy-pasted for brevity as it had no changes.
486
- handleDownload = async function () { if (!currentLightboxUrl) return; const spinner = lightboxDownload.querySelector('.spinner'); const icon = lightboxDownload.querySelector('svg'); spinner.style.display = 'block'; icon.style.display = 'none'; lightboxDownload.disabled = true; try { const response = await fetch(currentLightboxUrl); if (!response.ok) throw new Error('Network response was not ok.'); const blob = await response.blob(); const objectUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = objectUrl; a.download = `ai-edited-image-${Date.now()}.png`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(objectUrl); } catch (e) { console.error('Download failed:', e); alert('خطا در دانلود تصویر. لطفا دوباره تلاش کنید.'); } finally { spinner.style.display = 'none'; icon.style.display = 'block'; lightboxDownload.disabled = false; } };
487
  </script>
488
  </body>
489
  </html>
 
183
  .loading-text { font-weight: 500; color: var(--text-secondary); }
184
  #result-grid { display: none; grid-template-columns: repeat(2, 1fr); gap: 1.5rem; width: 100%; }
185
  #result-container.has-content #result-grid { display: grid; }
186
+ #result-grid img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--radius-input); cursor: pointer; transition: var(--transition-smooth); box-shadow: var(--shadow-md); border: 1px solid var(--panel-border); }
187
  #result-grid img:hover { transform: scale(1.05); box-shadow: var(--shadow-lg); z-index: 10; position: relative; }
188
  #error-message { color: var(--danger-color); text-align: center; margin-top: 1rem; display: none; font-weight: 500; }
189
 
 
200
  }
201
 
202
  #history-grid:empty::before { content: 'هنوز تصویری خلق نکرده‌اید. اولین ویرایش شما اینجا ذخیره خواهد شد.'; color: var(--text-secondary); grid-column: 1 / -1; text-align: center; padding: 3rem 1rem; background-color: var(--input-bg); border-radius: var(--radius-card); }
203
+ .history-item { position: relative; background-color: var(--input-bg); border-radius: var(--radius-card); border: 1px solid var(--panel-border); padding: 1rem; transition: var(--transition-smooth); }
204
  .history-item:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); }
205
 
206
  .history-item-grid {
 
224
  #lightbox-close { top: -50px; right: 0; }
225
  #lightbox-download { top: -50px; left: 0; }
226
 
 
227
  #lightbox-next {
228
+ right: -60px;
229
  top: 50%;
230
  transform: translateY(-50%);
231
  }
 
318
  <svg fill="white" viewBox="0 0 24 24"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>
319
  <div class="spinner"></div>
320
  </button>
 
321
  <button id="lightbox-next" title="بعدی" class="lightbox-btn">
322
  <svg fill="white" viewBox="0 0 24 24" width="24" height="24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6-6-6z"/></svg>
323
  </button>
 
325
  </div>
326
 
327
  <script>
328
+ // --- 1. ELEMENT SELECTORS ---
329
  const API_URL = 'https://alfa-editor-worker.onrender.com/api/edit';
 
330
  const uploadArea = document.getElementById('upload-area');
331
  const fileInput = document.getElementById('file-input');
332
  const previewImage = document.getElementById('preview-image-main');
333
  const removeFileBtn = document.getElementById('remove-file-btn-main');
 
334
  const promptInput = document.getElementById('prompt-input');
335
  const submitBtn = document.getElementById('submit-btn');
336
  const resultContainer = document.getElementById('result-container');
337
  const resultGrid = document.getElementById('result-grid');
338
+ const errorMessage = document.getElementById('error-message');
339
  const lightbox = document.getElementById('lightbox');
340
  const lightboxImg = document.getElementById('lightbox-img');
341
  const lightboxClose = document.getElementById('lightbox-close');
342
  const lightboxDownload = document.getElementById('lightbox-download');
343
+ const lightboxNext = document.getElementById('lightbox-next');
344
  const historyGrid = document.getElementById('history-grid');
345
  const clearHistoryBtn = document.getElementById('clear-history-btn');
346
 
347
+ // --- 2. STATE VARIABLES ---
348
  let uploadedFile = null;
349
  let currentLightboxUrl = null;
 
350
  let currentLightboxGroup = [];
351
  let currentLightboxIndex = 0;
352
 
353
+ // --- 3. FUNCTION DEFINITIONS ---
354
  const resetUploader = () => {
355
  uploadedFile = null;
356
  fileInput.value = '';
 
360
  };
361
 
362
  const handleFile = (file) => {
363
+ if (!file || !file.type.startsWith('image/')) {
364
+ displayError('لطفا یک فایل تصویری معتبر انتخاب کنید.');
365
+ return;
366
+ }
367
  uploadedFile = file;
368
  const reader = new FileReader();
369
  reader.onload = (e) => { previewImage.src = e.target.result; };
 
373
  clearResult();
374
  };
375
 
376
+ const checkFormState = () => {
377
+ submitBtn.disabled = !uploadedFile || promptInput.value.trim() === '';
378
+ };
 
 
379
 
380
+ const setLoading = (isLoading) => {
381
+ const btnSpinner = submitBtn.querySelector('.spinner');
382
+ const btnText = document.getElementById('btn-text');
383
+ if (isLoading) {
384
+ resultContainer.classList.remove('has-content');
385
+ resultContainer.classList.add('loading');
386
+ btnSpinner.style.display = 'inline-block';
387
+ btnText.textContent = 'در حال پردازش...';
388
+ submitBtn.disabled = true;
389
+ resultGrid.innerHTML = '';
390
+ errorMessage.style.display = 'none';
391
+ } else {
392
+ resultContainer.classList.remove('loading');
393
+ btnSpinner.style.display = 'none';
394
+ btnText.textContent = 'خلق کن';
395
+ checkFormState();
396
+ }
397
+ };
398
 
399
+ const displayResult = (imageUrls) => {
400
  resultGrid.innerHTML = '';
401
  imageUrls.forEach((url) => {
402
  const img = document.createElement('img');
403
  img.src = url;
404
  img.alt = 'تصویر ویرایش شده';
 
405
  img.addEventListener('click', () => openLightbox(url, imageUrls));
406
  resultGrid.appendChild(img);
407
  });
408
  resultContainer.classList.add('has-content');
409
+ };
410
 
411
+ const clearResult = () => {
412
+ resultGrid.innerHTML = '';
413
+ errorMessage.style.display = 'none';
414
+ resultContainer.classList.remove('has-content');
415
+ };
416
+
417
+ const displayError = (message) => {
418
+ errorMessage.textContent = message;
419
+ errorMessage.style.display = 'block';
420
+ };
421
+
422
+ const updateLightboxImage = () => {
423
  const newUrl = currentLightboxGroup[currentLightboxIndex];
424
  lightboxImg.src = newUrl;
425
+ currentLightboxUrl = newUrl;
426
+ };
427
 
428
+ const openLightbox = (clickedUrl, urlGroup) => {
429
  currentLightboxGroup = urlGroup;
430
  currentLightboxIndex = urlGroup.indexOf(clickedUrl);
431
  updateLightboxImage();
432
  lightboxNext.style.display = urlGroup.length > 1 ? 'flex' : 'none';
433
  lightbox.classList.add('visible');
434
+ };
435
 
436
+ const closeLightbox = () => {
437
  lightbox.classList.remove('visible');
438
+ currentLightboxGroup = [];
439
+ };
 
 
 
 
 
440
 
441
+ const handleDownload = async () => {
442
+ if (!currentLightboxUrl) return;
443
+ const spinner = lightboxDownload.querySelector('.spinner');
444
+ const icon = lightboxDownload.querySelector('svg');
445
+ spinner.style.display = 'block';
446
+ icon.style.display = 'none';
447
+ lightboxDownload.disabled = true;
448
+ try {
449
+ const response = await fetch(currentLightboxUrl);
450
+ if (!response.ok) throw new Error('Network response was not ok.');
451
+ const blob = await response.blob();
452
+ const objectUrl = URL.createObjectURL(blob);
453
+ const a = document.createElement('a');
454
+ a.href = objectUrl;
455
+ a.download = `ai-edited-image-${Date.now()}.png`;
456
+ document.body.appendChild(a);
457
+ a.click();
458
+ document.body.removeChild(a);
459
+ URL.revokeObjectURL(objectUrl);
460
+ } catch (e) {
461
+ console.error('Download failed:', e);
462
+ alert('خطا در دانلود تصویر. لطفا دوباره تلاش کنید.');
463
+ } finally {
464
+ spinner.style.display = 'none';
465
+ icon.style.display = 'block';
466
+ lightboxDownload.disabled = false;
467
+ }
468
+ };
469
+
470
+ const getHistory = () => JSON.parse(localStorage.getItem('aiPhotoshopHistory') || '[]');
471
+ const saveHistory = (history) => {
472
+ localStorage.setItem('aiPhotoshopHistory', JSON.stringify(history));
473
+ renderHistory();
474
+ };
475
+ const addToHistory = (item) => {
476
+ let history = getHistory();
477
+ history.unshift(item);
478
+ if (history.length > 15) history.pop();
479
+ saveHistory(history);
480
+ };
481
+ const handleClearHistory = () => {
482
+ if (confirm('آیا از پاک کردن تمام تاریخچه مطمئن هستید؟')) {
483
+ saveHistory([]);
484
+ }
485
+ };
486
+ const handleDeleteItem = (index) => {
487
+ let history = getHistory();
488
+ history.splice(index, 1);
489
+ saveHistory(history);
490
+ };
491
+
492
+ const renderHistory = () => {
493
  const history = getHistory();
494
  historyGrid.innerHTML = '';
495
  clearHistoryBtn.style.display = history.length > 0 ? 'flex' : 'none';
 
496
  history.forEach((item, index) => {
497
  const card = document.createElement('div');
498
  card.className = 'history-item';
499
 
 
500
  const deleteBtn = document.createElement('button');
501
  deleteBtn.className = 'history-delete-btn';
502
  deleteBtn.title = 'حذف این مورد';
 
506
 
507
  const imageGrid = document.createElement('div');
508
  imageGrid.className = 'history-item-grid';
 
509
  item.urls.forEach(url => {
510
  const img = document.createElement('img');
511
  img.src = url;
512
  img.alt = 'تصویر از تاریخچه';
 
513
  img.addEventListener('click', () => openLightbox(url, item.urls));
514
  imageGrid.appendChild(img);
515
  });
 
517
  card.appendChild(imageGrid);
518
  historyGrid.appendChild(card);
519
  });
 
 
 
 
 
 
 
520
  };
521
 
522
+ // --- 4. EVENT LISTENERS ---
523
+ document.addEventListener('DOMContentLoaded', () => {
524
+ renderHistory();
525
+ checkFormState();
526
+ });
527
+
528
+ removeFileBtn.addEventListener('click', (e) => {
529
+ e.preventDefault();
530
+ e.stopPropagation();
531
+ resetUploader();
532
+ });
533
+
534
+ fileInput.addEventListener('change', (e) => handleFile(e.target.files[0]));
535
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(e => {
536
+ uploadArea.addEventListener(e, p => { p.preventDefault(); p.stopPropagation(); });
537
+ });
538
+ ['dragenter', 'dragover'].forEach(e => {
539
+ uploadArea.addEventListener(e, () => { if (!uploadArea.classList.contains('has-file')) uploadArea.classList.add('drag-over'); });
540
+ });
541
+ ['dragleave', 'drop'].forEach(e => {
542
+ uploadArea.addEventListener(e, () => uploadArea.classList.remove('drag-over'));
543
+ });
544
+ uploadArea.addEventListener('drop', e => {
545
+ if (!uploadArea.classList.contains('has-file')) handleFile(e.dataTransfer.files[0]);
546
+ });
547
+
548
+ promptInput.addEventListener('input', checkFormState);
549
+
550
+ submitBtn.addEventListener('click', async () => {
551
+ if (submitBtn.disabled) return;
552
+ setLoading(true);
553
+ const formData = new FormData();
554
+ formData.append('image', uploadedFile);
555
+ formData.append('prompt', promptInput.value.trim());
556
+ try {
557
+ const response = await fetch(API_URL, { method: 'POST', body: formData });
558
+ if (!response.ok) {
559
+ const errorData = await response.json().catch(() => ({ error: `خطای سرور: ${response.statusText}` }));
560
+ throw new Error(errorData.error || `یک خطای ناشناخته رخ داد.`);
561
+ }
562
+ const result = await response.json();
563
+ if (result.image_urls && Array.isArray(result.image_urls) && result.image_urls.length > 0) {
564
+ displayResult(result.image_urls);
565
+ addToHistory({ prompt: promptInput.value.trim(), urls: result.image_urls });
566
+ } else {
567
+ throw new Error('پاسخ معتبری از سرور دریافت نشد.');
568
+ }
569
+ } catch (error) {
570
+ displayError(error.message);
571
+ } finally {
572
+ setLoading(false);
573
+ }
574
+ });
575
+
576
  lightboxClose.addEventListener('click', closeLightbox);
577
  lightbox.addEventListener('click', (e) => { if (e.target === lightbox) closeLightbox(); });
578
  lightboxDownload.addEventListener('click', handleDownload);
579
+ lightboxNext.addEventListener('click', () => {
580
+ currentLightboxIndex = (currentLightboxIndex + 1) % currentLightboxGroup.length;
581
+ updateLightboxImage();
582
+ });
583
  clearHistoryBtn.addEventListener('click', handleClearHistory);
 
 
 
 
584
  </script>
585
  </body>
586
  </html>