Spaces:
Running
Running
Update index.html
Browse files- index.html +69 -14
index.html
CHANGED
|
@@ -126,17 +126,34 @@
|
|
| 126 |
|
| 127 |
textarea { width: 100%; padding: 1rem 1.2rem; border-radius: var(--radius-input); border: 1px solid var(--input-border); background-color: var(--input-bg); color: var(--text-primary); box-shadow: var(--shadow-sm) inset; font-family: var(--app-font); font-size: 1rem; box-sizing: border-box; transition: var(--transition-smooth); min-height: 90px; resize: vertical; }
|
| 128 |
textarea:focus { outline: none; border-color: var(--accent-primary); box-shadow: 0 0 0 3px var(--accent-primary-glow), var(--shadow-sm) inset; background-color: var(--panel-bg); }
|
|
|
|
|
|
|
| 129 |
#submit-btn {
|
| 130 |
display: flex; align-items: center; justify-content: center; gap: 0.75rem; width: 100%; padding: 1.1rem;
|
| 131 |
-
font-size: 1.2rem; font-weight: 700;
|
| 132 |
-
|
| 133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
}
|
| 135 |
-
#submit-btn svg { width: 24px; height: 24px; margin-left: 4px; filter: drop-shadow(0 0 5px rgba(255,255,255,0.5)); }
|
| 136 |
-
#submit-btn:hover:not(:disabled) { transform: translateY(-5px) scale(1.02); box-shadow: 0 8px 20px -4px var(--accent-primary-glow), 0 8px 20px -4px var(--accent-secondary-glow); }
|
| 137 |
#submit-btn:disabled { background: var(--text-tertiary); cursor: not-allowed; box-shadow: none; opacity: 0.7; }
|
| 138 |
#submit-btn .spinner { width: 20px; height: 20px; border: 3px solid rgba(255, 255, 255, 0.4); border-top-color: #fff; border-radius: 50%; animation: spin 0.8s linear infinite; display: none; }
|
| 139 |
-
|
|
|
|
| 140 |
#result-container { min-height: 350px; position: relative; padding: 1rem; background-color: var(--input-bg); border-radius: var(--radius-card); border: 2px dashed var(--input-border); box-shadow: var(--shadow-sm) inset; transition: var(--transition-smooth); display: flex; align-items: center; justify-content: center; }
|
| 141 |
#result-container.loading, #result-container.has-content { border-style: solid; border-color: var(--panel-border); }
|
| 142 |
#loading-placeholder { display: none; }
|
|
@@ -252,10 +269,6 @@
|
|
| 252 |
background: linear-gradient(to right, #38bdf8, #bb86fc, #facc15);
|
| 253 |
animation: progress 7s infinite linear;
|
| 254 |
}
|
| 255 |
-
@keyframes progress {
|
| 256 |
-
0% { width: 0%; }
|
| 257 |
-
100% { width: 100%; }
|
| 258 |
-
}
|
| 259 |
|
| 260 |
#result-grid { display: none; grid-template-columns: 1fr; /* Changed for single result */ gap: 1.5rem; width: 100%; justify-items: center; }
|
| 261 |
#result-container.has-content #result-grid { display: grid; }
|
|
@@ -446,7 +459,7 @@
|
|
| 446 |
const uploadArea = document.getElementById('upload-area'); const fileInput = document.getElementById('file-input'); const previewImage = document.getElementById('preview-image-main'); const removeFileBtn = document.getElementById('remove-file-btn-main'); const promptInput = document.getElementById('prompt-input'); const submitBtn = document.getElementById('submit-btn'); const resultContainer = document.getElementById('result-container'); const resultGrid = document.getElementById('result-grid'); const errorMessage = document.getElementById('error-message'); const lightbox = document.getElementById('lightbox'); const lightboxImg = document.getElementById('lightbox-img'); const lightboxClose = document.getElementById('lightbox-close'); const lightboxDownload = document.getElementById('lightbox-download'); const lightboxNext = document.getElementById('lightbox-next'); const historyGrid = document.getElementById('history-grid'); const clearHistoryBtn = document.getElementById('clear-history-btn'); const confirmationModal = document.getElementById('confirmation-modal'); const modalMessageText = document.getElementById('modal-message-text'); const modalConfirmBtn = document.getElementById('modal-confirm-btn'); const modalCancelBtn = document.getElementById('modal-cancel-btn');
|
| 447 |
let uploadedFile = null; let currentLightboxUrl = null; let currentLightboxGroup = []; let currentLightboxIndex = 0;
|
| 448 |
|
| 449 |
-
// ---
|
| 450 |
const convertToPNG = (file) => {
|
| 451 |
return new Promise((resolve, reject) => {
|
| 452 |
const image = new Image();
|
|
@@ -497,9 +510,51 @@
|
|
| 497 |
checkFormState();
|
| 498 |
clearResult();
|
| 499 |
};
|
| 500 |
-
const showConfirmationModal = (message, onConfirm) => { modalMessageText.textContent = message; confirmationModal.classList.add('visible'); modalConfirmBtn.onclick = () => { onConfirm(); hideConfirmationModal(); }; modalCancelBtn.onclick = () => { hideConfirmationModal(); }; }; const hideConfirmationModal = () => { confirmationModal.classList.remove('visible'); modalConfirmBtn.onclick = null; modalCancelBtn.onclick = null; }; const resetUploader = () => { uploadedFile = null; fileInput.value = ''; previewImage.src = ''; uploadArea.classList.remove('has-file'); checkFormState(); }; const checkFormState = () => { submitBtn.disabled = !uploadedFile || promptInput.value.trim() === ''; }; const setLoading = (isLoading) => { const btnSpinner = submitBtn.querySelector('.spinner'); const btnText = document.getElementById('btn-text'); const btnIcon = submitBtn.querySelector('svg'); if (isLoading) { resultContainer.classList.remove('has-content'); resultContainer.classList.add('loading'); btnSpinner.style.display = 'inline-block'; btnIcon.style.display = 'none'; btnText.textContent = 'در حال پردازش...'; submitBtn.disabled = true; resultGrid.innerHTML = ''; errorMessage.style.display = 'none'; } else { resultContainer.classList.remove('loading'); btnSpinner.style.display = 'none'; btnIcon.style.display = 'inline-block'; btnText.textContent = 'ایجاد کن'; checkFormState(); } }; const displayResult = (imageUrls) => { resultGrid.innerHTML = ''; imageUrls.forEach((url) => { const img = document.createElement('img'); img.src = url; img.alt = 'تصویر ویرایش شده'; img.addEventListener('click', () => openLightbox(url, imageUrls)); resultGrid.appendChild(img); }); resultContainer.classList.add('has-content'); }; const clearResult = () => { resultGrid.innerHTML = ''; errorMessage.style.display = 'none'; resultContainer.classList.remove('has-content'); }; const displayError = (message) => { errorMessage.textContent = message; errorMessage.style.display = 'block'; }; const updateLightboxImage = () => { const newUrl = currentLightboxGroup[currentLightboxIndex]; lightboxImg.src = newUrl; currentLightboxUrl = newUrl; }; const openLightbox = (clickedUrl, urlGroup) => { currentLightboxGroup = urlGroup; currentLightboxIndex = urlGroup.indexOf(clickedUrl); updateLightboxImage(); lightboxNext.style.display = urlGroup.length > 1 ? 'flex' : 'none'; lightbox.classList.add('visible'); }; const closeLightbox = () => { lightbox.classList.remove('visible'); currentLightboxGroup = []; }; const handleDownload = async () => { 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; } };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 501 |
|
| 502 |
-
// ---
|
| 503 |
async function uploadFileToGradio(file) {
|
| 504 |
const formData = new FormData();
|
| 505 |
formData.append('files', file);
|
|
@@ -586,7 +641,7 @@
|
|
| 586 |
document.addEventListener('DOMContentLoaded', () => { renderHistory(); checkFormState(); });
|
| 587 |
removeFileBtn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); resetUploader(); }); fileInput.addEventListener('change', (e) => handleFile(e.target.files[0])); ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(e => { uploadArea.addEventListener(e, p => { p.preventDefault(); p.stopPropagation(); }); }); ['dragenter', 'dragover'].forEach(e => { uploadArea.addEventListener(e, () => { if (!uploadArea.classList.contains('has-file')) uploadArea.classList.add('drag-over'); }); }); ['dragleave', 'drop'].forEach(e => { uploadArea.addEventListener(e, () => uploadArea.classList.remove('drag-over')); }); uploadArea.addEventListener('drop', e => { if (!uploadArea.classList.contains('has-file')) handleFile(e.dataTransfer.files[0]); }); promptInput.addEventListener('input', checkFormState);
|
| 588 |
|
| 589 |
-
// ---
|
| 590 |
submitBtn.addEventListener('click', async () => {
|
| 591 |
if (submitBtn.disabled) return;
|
| 592 |
setLoading(true);
|
|
|
|
| 126 |
|
| 127 |
textarea { width: 100%; padding: 1rem 1.2rem; border-radius: var(--radius-input); border: 1px solid var(--input-border); background-color: var(--input-bg); color: var(--text-primary); box-shadow: var(--shadow-sm) inset; font-family: var(--app-font); font-size: 1rem; box-sizing: border-box; transition: var(--transition-smooth); min-height: 90px; resize: vertical; }
|
| 128 |
textarea:focus { outline: none; border-color: var(--accent-primary); box-shadow: 0 0 0 3px var(--accent-primary-glow), var(--shadow-sm) inset; background-color: var(--panel-bg); }
|
| 129 |
+
|
| 130 |
+
/* --- MODIFICATION START: Improved Button Style --- */
|
| 131 |
#submit-btn {
|
| 132 |
display: flex; align-items: center; justify-content: center; gap: 0.75rem; width: 100%; padding: 1.1rem;
|
| 133 |
+
font-size: 1.2rem; font-weight: 700;
|
| 134 |
+
background: linear-gradient(95deg, var(--accent-secondary) 0%, var(--accent-primary) 50%, var(--accent-secondary) 100%);
|
| 135 |
+
background-size: 200% auto;
|
| 136 |
+
color: #fff; border: none; border-radius: var(--radius-btn); cursor: pointer;
|
| 137 |
+
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
|
| 138 |
+
box-shadow: 0 6px 12px -3px var(--accent-primary-glow), 0 6px 12px -3px var(--accent-secondary-glow);
|
| 139 |
+
margin-top: 1.5rem;
|
| 140 |
+
position: relative;
|
| 141 |
+
z-index: 1;
|
| 142 |
+
overflow: hidden;
|
| 143 |
+
}
|
| 144 |
+
#submit-btn svg { width: 24px; height: 24px; margin-left: 4px; filter: drop-shadow(0 0 5px rgba(255,255,255,0.5)); transition: transform 0.3s ease; }
|
| 145 |
+
#submit-btn:hover:not(:disabled) {
|
| 146 |
+
background-position: right center;
|
| 147 |
+
transform: translateY(-4px);
|
| 148 |
+
box-shadow: 0 10px 20px -4px var(--accent-primary-glow), 0 10px 20px -4px var(--accent-secondary-glow);
|
| 149 |
+
}
|
| 150 |
+
#submit-btn:hover:not(:disabled) svg {
|
| 151 |
+
transform: scale(1.1) rotate(-15deg);
|
| 152 |
}
|
|
|
|
|
|
|
| 153 |
#submit-btn:disabled { background: var(--text-tertiary); cursor: not-allowed; box-shadow: none; opacity: 0.7; }
|
| 154 |
#submit-btn .spinner { width: 20px; height: 20px; border: 3px solid rgba(255, 255, 255, 0.4); border-top-color: #fff; border-radius: 50%; animation: spin 0.8s linear infinite; display: none; }
|
| 155 |
+
/* --- MODIFICATION END --- */
|
| 156 |
+
|
| 157 |
#result-container { min-height: 350px; position: relative; padding: 1rem; background-color: var(--input-bg); border-radius: var(--radius-card); border: 2px dashed var(--input-border); box-shadow: var(--shadow-sm) inset; transition: var(--transition-smooth); display: flex; align-items: center; justify-content: center; }
|
| 158 |
#result-container.loading, #result-container.has-content { border-style: solid; border-color: var(--panel-border); }
|
| 159 |
#loading-placeholder { display: none; }
|
|
|
|
| 269 |
background: linear-gradient(to right, #38bdf8, #bb86fc, #facc15);
|
| 270 |
animation: progress 7s infinite linear;
|
| 271 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 272 |
|
| 273 |
#result-grid { display: none; grid-template-columns: 1fr; /* Changed for single result */ gap: 1.5rem; width: 100%; justify-items: center; }
|
| 274 |
#result-container.has-content #result-grid { display: grid; }
|
|
|
|
| 459 |
const uploadArea = document.getElementById('upload-area'); const fileInput = document.getElementById('file-input'); const previewImage = document.getElementById('preview-image-main'); const removeFileBtn = document.getElementById('remove-file-btn-main'); const promptInput = document.getElementById('prompt-input'); const submitBtn = document.getElementById('submit-btn'); const resultContainer = document.getElementById('result-container'); const resultGrid = document.getElementById('result-grid'); const errorMessage = document.getElementById('error-message'); const lightbox = document.getElementById('lightbox'); const lightboxImg = document.getElementById('lightbox-img'); const lightboxClose = document.getElementById('lightbox-close'); const lightboxDownload = document.getElementById('lightbox-download'); const lightboxNext = document.getElementById('lightbox-next'); const historyGrid = document.getElementById('history-grid'); const clearHistoryBtn = document.getElementById('clear-history-btn'); const confirmationModal = document.getElementById('confirmation-modal'); const modalMessageText = document.getElementById('modal-message-text'); const modalConfirmBtn = document.getElementById('modal-confirm-btn'); const modalCancelBtn = document.getElementById('modal-cancel-btn');
|
| 460 |
let uploadedFile = null; let currentLightboxUrl = null; let currentLightboxGroup = []; let currentLightboxIndex = 0;
|
| 461 |
|
| 462 |
+
// --- HELPER FUNCTIONS ---
|
| 463 |
const convertToPNG = (file) => {
|
| 464 |
return new Promise((resolve, reject) => {
|
| 465 |
const image = new Image();
|
|
|
|
| 510 |
checkFormState();
|
| 511 |
clearResult();
|
| 512 |
};
|
| 513 |
+
const showConfirmationModal = (message, onConfirm) => { modalMessageText.textContent = message; confirmationModal.classList.add('visible'); modalConfirmBtn.onclick = () => { onConfirm(); hideConfirmationModal(); }; modalCancelBtn.onclick = () => { hideConfirmationModal(); }; }; const hideConfirmationModal = () => { confirmationModal.classList.remove('visible'); modalConfirmBtn.onclick = null; modalCancelBtn.onclick = null; }; const resetUploader = () => { uploadedFile = null; fileInput.value = ''; previewImage.src = ''; uploadArea.classList.remove('has-file'); checkFormState(); }; const checkFormState = () => { submitBtn.disabled = !uploadedFile || promptInput.value.trim() === ''; }; const setLoading = (isLoading) => { const btnSpinner = submitBtn.querySelector('.spinner'); const btnText = document.getElementById('btn-text'); const btnIcon = submitBtn.querySelector('svg'); if (isLoading) { resultContainer.classList.remove('has-content'); resultContainer.classList.add('loading'); btnSpinner.style.display = 'inline-block'; btnIcon.style.display = 'none'; btnText.textContent = 'در حال پردازش...'; submitBtn.disabled = true; resultGrid.innerHTML = ''; errorMessage.style.display = 'none'; } else { resultContainer.classList.remove('loading'); btnSpinner.style.display = 'none'; btnIcon.style.display = 'inline-block'; btnText.textContent = 'ایجاد کن'; checkFormState(); } }; const displayResult = (imageUrls) => { resultGrid.innerHTML = ''; imageUrls.forEach((url) => { const img = document.createElement('img'); img.src = url; img.alt = 'تصویر ویرایش شده'; img.addEventListener('click', () => openLightbox(url, imageUrls)); resultGrid.appendChild(img); }); resultContainer.classList.add('has-content'); }; const clearResult = () => { resultGrid.innerHTML = ''; errorMessage.style.display = 'none'; resultContainer.classList.remove('has-content'); }; const displayError = (message) => { errorMessage.textContent = message; errorMessage.style.display = 'block'; }; const updateLightboxImage = () => { const newUrl = currentLightboxGroup[currentLightboxIndex]; lightboxImg.src = newUrl; currentLightboxUrl = newUrl; }; const openLightbox = (clickedUrl, urlGroup) => { currentLightboxGroup = urlGroup; currentLightboxIndex = urlGroup.indexOf(clickedUrl); updateLightboxImage(); lightboxNext.style.display = urlGroup.length > 1 ? 'flex' : 'none'; lightbox.classList.add('visible'); }; const closeLightbox = () => { lightbox.classList.remove('visible'); currentLightboxGroup = []; }; const handleDownload = async () => { 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; } };
|
| 514 |
+
|
| 515 |
+
// --- MODIFICATION START: History Management with Expiration ---
|
| 516 |
+
const getHistory = () => {
|
| 517 |
+
const historyFromStorage = JSON.parse(localStorage.getItem('aiPhotoshopHistory') || '[]');
|
| 518 |
+
if (!Array.isArray(historyFromStorage)) return [];
|
| 519 |
+
|
| 520 |
+
const FIVE_DAYS_IN_MS = 5 * 24 * 60 * 60 * 1000;
|
| 521 |
+
const now = Date.now();
|
| 522 |
+
|
| 523 |
+
// Filter out items older than 5 days
|
| 524 |
+
const freshHistory = historyFromStorage.filter(item => {
|
| 525 |
+
// For backward compatibility, if 'createdAt' timestamp doesn't exist, we keep the item.
|
| 526 |
+
// This prevents deleting old history items that were created before this feature was added.
|
| 527 |
+
if (typeof item.createdAt !== 'number') {
|
| 528 |
+
return true;
|
| 529 |
+
}
|
| 530 |
+
return (now - item.createdAt) < FIVE_DAYS_IN_MS;
|
| 531 |
+
});
|
| 532 |
+
|
| 533 |
+
// If the filtering process removed any items, we update localStorage to clean it up.
|
| 534 |
+
if (freshHistory.length < historyFromStorage.length) {
|
| 535 |
+
localStorage.setItem('aiPhotoshopHistory', JSON.stringify(freshHistory));
|
| 536 |
+
}
|
| 537 |
+
|
| 538 |
+
return freshHistory;
|
| 539 |
+
};
|
| 540 |
+
|
| 541 |
+
const saveHistory = (history) => { localStorage.setItem('aiPhotoshopHistory', JSON.stringify(history)); renderHistory(); };
|
| 542 |
+
|
| 543 |
+
const addToHistory = (item) => {
|
| 544 |
+
let history = getHistory(); // getHistory now filters expired items
|
| 545 |
+
const newItem = {
|
| 546 |
+
...item,
|
| 547 |
+
createdAt: Date.now() // Add timestamp when creating a history item
|
| 548 |
+
};
|
| 549 |
+
history.unshift(newItem);
|
| 550 |
+
if (history.length > 15) history.pop();
|
| 551 |
+
saveHistory(history);
|
| 552 |
+
};
|
| 553 |
+
// --- MODIFICATION END ---
|
| 554 |
+
|
| 555 |
+
const handleClearHistory = () => { showConfirmationModal('آیا از پاک کردن تمام تاریخچه مطمئن هستید؟ این عمل غیرقابل بازگشت است.', () => { saveHistory([]); }); }; const handleDeleteItem = (index) => { showConfirmationModal('آیا از حذف این مورد از تاریخچه مطمئن هستید؟', () => { let history = getHistory(); history.splice(index, 1); saveHistory(history); }); }; const renderHistory = () => { const history = getHistory(); historyGrid.innerHTML = ''; clearHistoryBtn.style.display = history.length > 0 ? 'flex' : 'none'; history.forEach((item, index) => { const card = document.createElement('div'); card.className = 'history-item'; const deleteBtn = document.createElement('button'); deleteBtn.className = 'history-delete-btn'; deleteBtn.title = 'حذف این مورد'; deleteBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>`; deleteBtn.onclick = () => handleDeleteItem(index); card.appendChild(deleteBtn); const imageGrid = document.createElement('div'); imageGrid.className = 'history-item-grid'; item.urls.forEach(url => { const img = document.createElement('img'); img.src = url; img.alt = 'تصویر از تاریخچه'; img.addEventListener('click', () => openLightbox(url, item.urls)); imageGrid.appendChild(img); }); card.appendChild(imageGrid); historyGrid.appendChild(card); }); };
|
| 556 |
|
| 557 |
+
// --- GRADIO API HELPER FUNCTIONS ---
|
| 558 |
async function uploadFileToGradio(file) {
|
| 559 |
const formData = new FormData();
|
| 560 |
formData.append('files', file);
|
|
|
|
| 641 |
document.addEventListener('DOMContentLoaded', () => { renderHistory(); checkFormState(); });
|
| 642 |
removeFileBtn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); resetUploader(); }); fileInput.addEventListener('change', (e) => handleFile(e.target.files[0])); ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(e => { uploadArea.addEventListener(e, p => { p.preventDefault(); p.stopPropagation(); }); }); ['dragenter', 'dragover'].forEach(e => { uploadArea.addEventListener(e, () => { if (!uploadArea.classList.contains('has-file')) uploadArea.classList.add('drag-over'); }); }); ['dragleave', 'drop'].forEach(e => { uploadArea.addEventListener(e, () => uploadArea.classList.remove('drag-over')); }); uploadArea.addEventListener('drop', e => { if (!uploadArea.classList.contains('has-file')) handleFile(e.dataTransfer.files[0]); }); promptInput.addEventListener('input', checkFormState);
|
| 643 |
|
| 644 |
+
// --- SUBMIT BUTTON LOGIC ---
|
| 645 |
submitBtn.addEventListener('click', async () => {
|
| 646 |
if (submitBtn.disabled) return;
|
| 647 |
setLoading(true);
|