Spaces:
Running
Running
Update index.html
Browse files- index.html +26 -47
index.html
CHANGED
|
@@ -75,7 +75,9 @@
|
|
| 75 |
|
| 76 |
.form-group { margin-bottom: 2.5rem; }
|
| 77 |
.form-group:last-child { margin-bottom: 0; }
|
| 78 |
-
|
|
|
|
|
|
|
| 79 |
display: flex;
|
| 80 |
align-items: center;
|
| 81 |
gap: 0.75rem;
|
|
@@ -84,7 +86,7 @@
|
|
| 84 |
font-size: 1.2em;
|
| 85 |
margin-bottom: 1.2rem;
|
| 86 |
}
|
| 87 |
-
|
| 88 |
|
| 89 |
/* --- Uploader Style with Image Preview --- */
|
| 90 |
#upload-container.has-file #upload-area { display: none; }
|
|
@@ -189,7 +191,7 @@
|
|
| 189 |
#lightbox-close { top: -50px; right: 0; font-size: 1.8rem; }
|
| 190 |
#lightbox-download { top: -50px; left: 0; }
|
| 191 |
#lightbox-download svg { width: 22px; height: 22px; }
|
| 192 |
-
|
| 193 |
|
| 194 |
@media (max-width: 768px) {
|
| 195 |
main, .gallery-section { padding: 1.5rem; }
|
|
@@ -206,18 +208,19 @@
|
|
| 206 |
</header>
|
| 207 |
|
| 208 |
<main>
|
|
|
|
| 209 |
<div class="form-group">
|
| 210 |
-
<
|
| 211 |
-
<svg xmlns="http://www.
|
| 212 |
۱. تصویر خود را انتخاب کنید
|
| 213 |
-
</
|
| 214 |
<div id="upload-container">
|
| 215 |
-
<label id="upload-area">
|
| 216 |
<div id="upload-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg></div>
|
| 217 |
<p>فایل تصویر را اینجا بکشید یا برای انتخاب کلیک کنید</p>
|
| 218 |
</label>
|
| 219 |
<div id="file-preview">
|
| 220 |
-
<img id="preview-image" src="" alt="Preview">
|
| 221 |
<div id="file-details">
|
| 222 |
<span id="file-name"></span>
|
| 223 |
<button type="button" id="remove-file-btn">حذف و انتخاب مجدد</button>
|
|
@@ -241,10 +244,10 @@
|
|
| 241 |
</div>
|
| 242 |
|
| 243 |
<div class="form-group">
|
| 244 |
-
<
|
| 245 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 3L12 8L17 10L12 12L10 17L8 12L3 10L8 8L10 3z"/><path d="M21 14l-1.5 3-3-1.5 3-3 1.5 3z"/><path d="M19.5 2.5l-3 1.5 1.5 3 3-1.5-1.5-3z"/></svg>
|
| 246 |
۳. نتیجه را ببینید
|
| 247 |
-
</
|
| 248 |
<div id="result-container">
|
| 249 |
<div id="loading-placeholder">
|
| 250 |
<div class="orbital-loader"><div class="orbit"><div class="satellite"></div></div><div class="orbit"><div class="satellite"></div></div></div>
|
|
@@ -257,10 +260,10 @@
|
|
| 257 |
|
| 258 |
<section class="gallery-section">
|
| 259 |
<div class="gallery-header">
|
| 260 |
-
<
|
| 261 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18"/><path d="M9 21V9"/></svg>
|
| 262 |
گالری و تاریخچه شما
|
| 263 |
-
</
|
| 264 |
<button id="clear-history-btn">
|
| 265 |
<svg xmlns="http://www.w3.org/2000/svg" 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>
|
| 266 |
<span>پاک کردن همه</span>
|
|
@@ -274,9 +277,9 @@
|
|
| 274 |
<div id="lightbox-content">
|
| 275 |
<img id="lightbox-img" src="">
|
| 276 |
<button id="lightbox-close" class="lightbox-btn">×</button>
|
| 277 |
-
|
|
|
|
| 278 |
<svg fill="white" viewBox="0 0 24 24"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>
|
| 279 |
-
<div class="spinner"></div>
|
| 280 |
</a>
|
| 281 |
</div>
|
| 282 |
</div>
|
|
@@ -306,7 +309,6 @@
|
|
| 306 |
const clearHistoryBtn = document.getElementById('clear-history-btn');
|
| 307 |
|
| 308 |
let uploadedFile = null;
|
| 309 |
-
let currentLightboxUrl = null;
|
| 310 |
|
| 311 |
// --- Uploader Logic ---
|
| 312 |
const resetUploader = () => {
|
|
@@ -328,7 +330,11 @@
|
|
| 328 |
checkFormState();
|
| 329 |
clearResult();
|
| 330 |
};
|
|
|
|
|
|
|
|
|
|
| 331 |
uploadArea.addEventListener('click', () => fileInput.click());
|
|
|
|
| 332 |
fileInput.addEventListener('change', (e) => handleFile(e.target.files[0]));
|
| 333 |
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(e => uploadArea.addEventListener(e, p => { p.preventDefault(); p.stopPropagation(); }));
|
| 334 |
['dragenter', 'dragover'].forEach(e => uploadArea.addEventListener(e, () => uploadArea.classList.add('drag-over')));
|
|
@@ -397,47 +403,20 @@
|
|
| 397 |
errorMessage.style.display = 'block';
|
| 398 |
}
|
| 399 |
|
| 400 |
-
// --- Lightbox
|
| 401 |
function openLightbox(url) {
|
| 402 |
-
currentLightboxUrl = url;
|
| 403 |
lightboxImg.src = url;
|
|
|
|
| 404 |
lightbox.classList.add('visible');
|
| 405 |
}
|
| 406 |
function closeLightbox() {
|
| 407 |
lightbox.classList.remove('visible');
|
| 408 |
-
|
| 409 |
-
}
|
| 410 |
-
async function handleDownload() {
|
| 411 |
-
if (!currentLightboxUrl) return;
|
| 412 |
-
const downloadBtn = lightboxDownload;
|
| 413 |
-
const spinner = downloadBtn.querySelector('.spinner');
|
| 414 |
-
const icon = downloadBtn.querySelector('svg');
|
| 415 |
-
|
| 416 |
-
spinner.style.display = 'block';
|
| 417 |
-
icon.style.display = 'none';
|
| 418 |
-
try {
|
| 419 |
-
const response = await fetch(currentLightboxUrl);
|
| 420 |
-
const blob = await response.blob();
|
| 421 |
-
const objectUrl = URL.createObjectURL(blob);
|
| 422 |
-
const a = document.createElement('a');
|
| 423 |
-
a.href = objectUrl;
|
| 424 |
-
a.download = `edited-image-${Date.now()}.png`;
|
| 425 |
-
document.body.appendChild(a);
|
| 426 |
-
a.click();
|
| 427 |
-
document.body.removeChild(a);
|
| 428 |
-
URL.revokeObjectURL(objectUrl);
|
| 429 |
-
} catch (e) {
|
| 430 |
-
console.error('Download failed:', e);
|
| 431 |
-
alert('خطا در دانلود تصویر. لطفا دوباره تلاش کنید.');
|
| 432 |
-
} finally {
|
| 433 |
-
spinner.style.display = 'none';
|
| 434 |
-
icon.style.display = 'block';
|
| 435 |
-
}
|
| 436 |
}
|
|
|
|
| 437 |
lightboxClose.addEventListener('click', closeLightbox);
|
| 438 |
lightbox.addEventListener('click', (e) => { if (e.target === lightbox) closeLightbox(); });
|
| 439 |
-
|
| 440 |
-
|
| 441 |
|
| 442 |
// --- History Management with Individual Delete ---
|
| 443 |
const getHistory = () => JSON.parse(localStorage.getItem('aiPhotoshopHistory') || '[]');
|
|
|
|
| 75 |
|
| 76 |
.form-group { margin-bottom: 2.5rem; }
|
| 77 |
.form-group:last-child { margin-bottom: 0; }
|
| 78 |
+
|
| 79 |
+
/* --- CHANGE 1: Made the selector more generic to apply to any tag, not just label --- */
|
| 80 |
+
.form-label {
|
| 81 |
display: flex;
|
| 82 |
align-items: center;
|
| 83 |
gap: 0.75rem;
|
|
|
|
| 86 |
font-size: 1.2em;
|
| 87 |
margin-bottom: 1.2rem;
|
| 88 |
}
|
| 89 |
+
.form-label svg { width: 24px; height: 24px; color: var(--accent-primary); }
|
| 90 |
|
| 91 |
/* --- Uploader Style with Image Preview --- */
|
| 92 |
#upload-container.has-file #upload-area { display: none; }
|
|
|
|
| 191 |
#lightbox-close { top: -50px; right: 0; font-size: 1.8rem; }
|
| 192 |
#lightbox-download { top: -50px; left: 0; }
|
| 193 |
#lightbox-download svg { width: 22px; height: 22px; }
|
| 194 |
+
/* --- CHANGE 2: Spinner CSS removed as it's no longer needed --- */
|
| 195 |
|
| 196 |
@media (max-width: 768px) {
|
| 197 |
main, .gallery-section { padding: 1.5rem; }
|
|
|
|
| 208 |
</header>
|
| 209 |
|
| 210 |
<main>
|
| 211 |
+
<!-- --- CHANGE 1: Simplified the structure to exactly match the screenshot's concept --- -->
|
| 212 |
<div class="form-group">
|
| 213 |
+
<div class="form-label">
|
| 214 |
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4Z"/></svg>
|
| 215 |
۱. تصویر خود را انتخاب کنید
|
| 216 |
+
</div>
|
| 217 |
<div id="upload-container">
|
| 218 |
+
<label id="upload-area" for="file-input">
|
| 219 |
<div id="upload-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg></div>
|
| 220 |
<p>فایل تصویر را اینجا بکشید یا برای انتخاب کلیک کنید</p>
|
| 221 |
</label>
|
| 222 |
<div id="file-preview">
|
| 223 |
+
<img id="preview-image" src="" alt="Preview">
|
| 224 |
<div id="file-details">
|
| 225 |
<span id="file-name"></span>
|
| 226 |
<button type="button" id="remove-file-btn">حذف و انتخاب مجدد</button>
|
|
|
|
| 244 |
</div>
|
| 245 |
|
| 246 |
<div class="form-group">
|
| 247 |
+
<div class="form-label">
|
| 248 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 3L12 8L17 10L12 12L10 17L8 12L3 10L8 8L10 3z"/><path d="M21 14l-1.5 3-3-1.5 3-3 1.5 3z"/><path d="M19.5 2.5l-3 1.5 1.5 3 3-1.5-1.5-3z"/></svg>
|
| 249 |
۳. نتیجه را ببینید
|
| 250 |
+
</div>
|
| 251 |
<div id="result-container">
|
| 252 |
<div id="loading-placeholder">
|
| 253 |
<div class="orbital-loader"><div class="orbit"><div class="satellite"></div></div><div class="orbit"><div class="satellite"></div></div></div>
|
|
|
|
| 260 |
|
| 261 |
<section class="gallery-section">
|
| 262 |
<div class="gallery-header">
|
| 263 |
+
<div class="form-label">
|
| 264 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18"/><path d="M9 21V9"/></svg>
|
| 265 |
گالری و تاریخچه شما
|
| 266 |
+
</div>
|
| 267 |
<button id="clear-history-btn">
|
| 268 |
<svg xmlns="http://www.w3.org/2000/svg" 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>
|
| 269 |
<span>پاک کردن همه</span>
|
|
|
|
| 277 |
<div id="lightbox-content">
|
| 278 |
<img id="lightbox-img" src="">
|
| 279 |
<button id="lightbox-close" class="lightbox-btn">×</button>
|
| 280 |
+
<!-- --- CHANGE 2: Added 'download' attribute and removed spinner div. It's now a simple download link. --- -->
|
| 281 |
+
<a id="lightbox-download" title="دانلود تصویر" class="lightbox-btn" download>
|
| 282 |
<svg fill="white" viewBox="0 0 24 24"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>
|
|
|
|
| 283 |
</a>
|
| 284 |
</div>
|
| 285 |
</div>
|
|
|
|
| 309 |
const clearHistoryBtn = document.getElementById('clear-history-btn');
|
| 310 |
|
| 311 |
let uploadedFile = null;
|
|
|
|
| 312 |
|
| 313 |
// --- Uploader Logic ---
|
| 314 |
const resetUploader = () => {
|
|
|
|
| 330 |
checkFormState();
|
| 331 |
clearResult();
|
| 332 |
};
|
| 333 |
+
|
| 334 |
+
// This line was slightly modified to not need a specific ID on the clickable area
|
| 335 |
+
// since the <label> now has a 'for' attribute pointing to the input.
|
| 336 |
uploadArea.addEventListener('click', () => fileInput.click());
|
| 337 |
+
|
| 338 |
fileInput.addEventListener('change', (e) => handleFile(e.target.files[0]));
|
| 339 |
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(e => uploadArea.addEventListener(e, p => { p.preventDefault(); p.stopPropagation(); }));
|
| 340 |
['dragenter', 'dragover'].forEach(e => uploadArea.addEventListener(e, () => uploadArea.classList.add('drag-over')));
|
|
|
|
| 403 |
errorMessage.style.display = 'block';
|
| 404 |
}
|
| 405 |
|
| 406 |
+
// --- CHANGE 2: Simplified Lightbox and Download logic ---
|
| 407 |
function openLightbox(url) {
|
|
|
|
| 408 |
lightboxImg.src = url;
|
| 409 |
+
lightboxDownload.href = url; // Set the href for the download link
|
| 410 |
lightbox.classList.add('visible');
|
| 411 |
}
|
| 412 |
function closeLightbox() {
|
| 413 |
lightbox.classList.remove('visible');
|
| 414 |
+
lightboxDownload.href = '#'; // Clear href on close
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 415 |
}
|
| 416 |
+
|
| 417 |
lightboxClose.addEventListener('click', closeLightbox);
|
| 418 |
lightbox.addEventListener('click', (e) => { if (e.target === lightbox) closeLightbox(); });
|
| 419 |
+
// The complex handleDownload function and its event listener are no longer needed.
|
|
|
|
| 420 |
|
| 421 |
// --- History Management with Individual Delete ---
|
| 422 |
const getHistory = () => JSON.parse(localStorage.getItem('aiPhotoshopHistory') || '[]');
|