Update index.html
Browse files- index.html +114 -24
index.html
CHANGED
|
@@ -231,13 +231,15 @@
|
|
| 231 |
justify-content: center;
|
| 232 |
margin: 0 auto 0.75rem;
|
| 233 |
}
|
| 234 |
-
.ratio-icon > div {
|
| 235 |
background-color: var(--panel-bg);
|
| 236 |
border: 2px solid var(--text-tertiary);
|
| 237 |
border-radius: 6px;
|
| 238 |
transition: var(--transition-smooth);
|
|
|
|
| 239 |
}
|
| 240 |
-
.ratio-option.active .ratio-icon > div
|
|
|
|
| 241 |
border-color: var(--accent-primary);
|
| 242 |
background-color: var(--accent-primary-glow);
|
| 243 |
}
|
|
@@ -252,7 +254,10 @@
|
|
| 252 |
#icon-portrait > div { width: 28px; height: 50px; }
|
| 253 |
#icon-landscape > div { width: 60px; height: 34px; }
|
| 254 |
#icon-square > div { width: 45px; height: 45px; }
|
| 255 |
-
#icon-
|
|
|
|
|
|
|
|
|
|
| 256 |
|
| 257 |
#submit-btn {
|
| 258 |
display: flex; align-items: center; justify-content: center; gap: 0.75rem; width: 100%; padding: 1.1rem;
|
|
@@ -288,7 +293,7 @@
|
|
| 288 |
|
| 289 |
.output-details { display: none !important; }
|
| 290 |
|
| 291 |
-
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(18, 24, 38, 0.6); backdrop-filter: blur(10px) saturate(150%); display: none; justify-content: center; align-items: center; z-index: 1000; }
|
| 292 |
.modal-content {
|
| 293 |
background: var(--panel-bg);
|
| 294 |
padding: 2rem 1rem;
|
|
@@ -301,7 +306,6 @@
|
|
| 301 |
position: relative;
|
| 302 |
box-shadow: var(--shadow-xl);
|
| 303 |
border: 1px solid var(--panel-border);
|
| 304 |
-
animation: fadeIn 0.3s ease;
|
| 305 |
}
|
| 306 |
.modal-header { display: flex; justify-content: center; align-items: center; border-bottom: 1px solid var(--panel-border); padding-bottom: 1rem; margin-bottom: 1.5rem; position: relative; min-height: 50px;}
|
| 307 |
.modal-header h2 { margin: 0; font-size: 1.8rem; font-weight: 700; color: var(--text-primary); }
|
|
@@ -315,12 +319,10 @@
|
|
| 315 |
gap: 1rem;
|
| 316 |
padding: 10px;
|
| 317 |
}
|
| 318 |
-
|
| 319 |
-
/* <<< START: روش جدید و سازگار برای ساخت مربع >>> */
|
| 320 |
.lora-card {
|
| 321 |
-
position: relative;
|
| 322 |
height: 0;
|
| 323 |
-
padding-bottom: 100%;
|
| 324 |
border-radius: var(--radius-input);
|
| 325 |
overflow: hidden;
|
| 326 |
cursor: pointer;
|
|
@@ -328,9 +330,8 @@
|
|
| 328 |
background-color: var(--input-bg);
|
| 329 |
border: 1px solid transparent;
|
| 330 |
box-shadow: var(--shadow-sm);
|
| 331 |
-
-webkit-user-select: none;
|
| 332 |
-
|
| 333 |
-
user-select: none; /* Standard syntax */
|
| 334 |
}
|
| 335 |
|
| 336 |
.lora-card:hover {
|
|
@@ -340,17 +341,15 @@
|
|
| 340 |
}
|
| 341 |
|
| 342 |
.lora-card img {
|
| 343 |
-
position: absolute;
|
| 344 |
top: 0;
|
| 345 |
left: 0;
|
| 346 |
width: 100%;
|
| 347 |
-
height: 100%;
|
| 348 |
object-fit: cover;
|
| 349 |
transition: opacity 0.3s ease-in-out;
|
| 350 |
opacity: 0;
|
| 351 |
}
|
| 352 |
-
/* <<< END: روش جدید و سازگار برای ساخت مربع >>> */
|
| 353 |
-
|
| 354 |
.lora-card img.loaded {
|
| 355 |
opacity: 1;
|
| 356 |
}
|
|
@@ -421,6 +420,17 @@
|
|
| 421 |
font-weight: 500;
|
| 422 |
}
|
| 423 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 424 |
@media (max-width: 768px) {
|
| 425 |
main { padding: 1.5rem; } h1 { font-size: 2.2rem; }
|
| 426 |
.aspect-ratio-selector { grid-template-columns: repeat(2, 1fr); }
|
|
@@ -473,9 +483,19 @@
|
|
| 473 |
<div class="ratio-icon" id="icon-landscape"><div></div></div>
|
| 474 |
<div class="ratio-label">افقی ۱۶:۹</div>
|
| 475 |
</div>
|
| 476 |
-
<div class="ratio-option" data-ratio="
|
| 477 |
-
<div class="ratio-icon" id="icon-
|
| 478 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 479 |
</div>
|
| 480 |
<div class="ratio-option active" data-ratio="1:1">
|
| 481 |
<div class="ratio-icon" id="icon-square"><div></div></div>
|
|
@@ -513,6 +533,24 @@
|
|
| 513 |
<div id="lora-grid"></div>
|
| 514 |
</div>
|
| 515 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 516 |
|
| 517 |
<script type="module">
|
| 518 |
import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
|
|
@@ -2247,9 +2285,18 @@
|
|
| 2247 |
const originalModalTitleHTML = modalTitle.innerHTML;
|
| 2248 |
let longPressTimer = null;
|
| 2249 |
let longPressJustHappened = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2250 |
|
| 2251 |
let selectedLora = null;
|
| 2252 |
let selectedRatio = '1:1';
|
|
|
|
|
|
|
| 2253 |
let imageObserver = null;
|
| 2254 |
let fluxClient = null;
|
| 2255 |
let countdownInterval = null;
|
|
@@ -2501,10 +2548,12 @@
|
|
| 2501 |
|
| 2502 |
setLoadingState(true, 'در حال پردازش...');
|
| 2503 |
const getDimensions = (ratio) => {
|
|
|
|
|
|
|
|
|
|
| 2504 |
switch (ratio) {
|
| 2505 |
-
case '9:16': return { width:
|
| 2506 |
-
case '16:9': return { width:
|
| 2507 |
-
case '4:3': return { width: 1152, height: 864 };
|
| 2508 |
default: return { width: 1024, height: 1024 };
|
| 2509 |
}
|
| 2510 |
};
|
|
@@ -2621,9 +2670,50 @@
|
|
| 2621 |
ratioSelector.addEventListener('click', (event) => {
|
| 2622 |
const selectedOption = event.target.closest('.ratio-option');
|
| 2623 |
if (!selectedOption) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2624 |
ratioSelector.querySelectorAll('.ratio-option').forEach(opt => opt.classList.remove('active'));
|
| 2625 |
-
|
| 2626 |
-
|
|
|
|
|
|
|
| 2627 |
});
|
| 2628 |
|
| 2629 |
clearResult();
|
|
|
|
| 231 |
justify-content: center;
|
| 232 |
margin: 0 auto 0.75rem;
|
| 233 |
}
|
| 234 |
+
.ratio-icon > div, .ratio-icon > svg {
|
| 235 |
background-color: var(--panel-bg);
|
| 236 |
border: 2px solid var(--text-tertiary);
|
| 237 |
border-radius: 6px;
|
| 238 |
transition: var(--transition-smooth);
|
| 239 |
+
box-sizing: border-box;
|
| 240 |
}
|
| 241 |
+
.ratio-option.active .ratio-icon > div,
|
| 242 |
+
.ratio-option.active .ratio-icon > svg {
|
| 243 |
border-color: var(--accent-primary);
|
| 244 |
background-color: var(--accent-primary-glow);
|
| 245 |
}
|
|
|
|
| 254 |
#icon-portrait > div { width: 28px; height: 50px; }
|
| 255 |
#icon-landscape > div { width: 60px; height: 34px; }
|
| 256 |
#icon-square > div { width: 45px; height: 45px; }
|
| 257 |
+
#icon-custom > svg { width: 45px; height: 45px; padding: 8px; color: var(--text-tertiary); }
|
| 258 |
+
.ratio-option.active #icon-custom > svg { color: var(--accent-primary); }
|
| 259 |
+
.custom-ratio-value { font-size: 0.75rem; color: var(--text-secondary); margin-top: 2px; height: 1em; }
|
| 260 |
+
|
| 261 |
|
| 262 |
#submit-btn {
|
| 263 |
display: flex; align-items: center; justify-content: center; gap: 0.75rem; width: 100%; padding: 1.1rem;
|
|
|
|
| 293 |
|
| 294 |
.output-details { display: none !important; }
|
| 295 |
|
| 296 |
+
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(18, 24, 38, 0.6); backdrop-filter: blur(10px) saturate(150%); display: none; justify-content: center; align-items: center; z-index: 1000; animation: fadeIn 0.3s ease; }
|
| 297 |
.modal-content {
|
| 298 |
background: var(--panel-bg);
|
| 299 |
padding: 2rem 1rem;
|
|
|
|
| 306 |
position: relative;
|
| 307 |
box-shadow: var(--shadow-xl);
|
| 308 |
border: 1px solid var(--panel-border);
|
|
|
|
| 309 |
}
|
| 310 |
.modal-header { display: flex; justify-content: center; align-items: center; border-bottom: 1px solid var(--panel-border); padding-bottom: 1rem; margin-bottom: 1.5rem; position: relative; min-height: 50px;}
|
| 311 |
.modal-header h2 { margin: 0; font-size: 1.8rem; font-weight: 700; color: var(--text-primary); }
|
|
|
|
| 319 |
gap: 1rem;
|
| 320 |
padding: 10px;
|
| 321 |
}
|
|
|
|
|
|
|
| 322 |
.lora-card {
|
| 323 |
+
position: relative;
|
| 324 |
height: 0;
|
| 325 |
+
padding-bottom: 100%;
|
| 326 |
border-radius: var(--radius-input);
|
| 327 |
overflow: hidden;
|
| 328 |
cursor: pointer;
|
|
|
|
| 330 |
background-color: var(--input-bg);
|
| 331 |
border: 1px solid transparent;
|
| 332 |
box-shadow: var(--shadow-sm);
|
| 333 |
+
-webkit-user-select: none;
|
| 334 |
+
user-select: none;
|
|
|
|
| 335 |
}
|
| 336 |
|
| 337 |
.lora-card:hover {
|
|
|
|
| 341 |
}
|
| 342 |
|
| 343 |
.lora-card img {
|
| 344 |
+
position: absolute;
|
| 345 |
top: 0;
|
| 346 |
left: 0;
|
| 347 |
width: 100%;
|
| 348 |
+
height: 100%;
|
| 349 |
object-fit: cover;
|
| 350 |
transition: opacity 0.3s ease-in-out;
|
| 351 |
opacity: 0;
|
| 352 |
}
|
|
|
|
|
|
|
| 353 |
.lora-card img.loaded {
|
| 354 |
opacity: 1;
|
| 355 |
}
|
|
|
|
| 420 |
font-weight: 500;
|
| 421 |
}
|
| 422 |
|
| 423 |
+
.modal-content-small { background: var(--panel-bg); padding: 2rem; border-radius: var(--radius-card); max-width: 350px; width: 90%; text-align: center; box-shadow: var(--shadow-xl); position: relative; }
|
| 424 |
+
.modal-content-small h3 { margin-top: 0; margin-bottom: 1.5rem; font-size: 1.5rem; color: var(--text-primary); }
|
| 425 |
+
.modal-content-small .input-group { margin-bottom: 1rem; text-align: right; }
|
| 426 |
+
.modal-content-small label { display: block; margin-bottom: 0.5rem; font-weight: 600; color: var(--text-secondary); font-size: 0.9rem; }
|
| 427 |
+
.modal-content-small input { width: 100%; padding: 0.8rem 1rem; 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); }
|
| 428 |
+
.modal-content-small input: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); }
|
| 429 |
+
#confirm-custom-size-btn { width: 100%; padding: 0.9rem; margin-top: 1rem; font-size: 1rem; font-weight: 700; background-color: var(--accent-primary); color: #fff; border: none; border-radius: var(--radius-btn); cursor: pointer; transition: var(--transition-smooth); }
|
| 430 |
+
#confirm-custom-size-btn:hover { background-color: var(--accent-primary-hover); }
|
| 431 |
+
#close-custom-modal-btn { position: absolute; top: 10px; left: 10px; background: transparent; border: none; font-size: 2rem; cursor: pointer; color: var(--text-tertiary); line-height: 1; padding: 0.5rem; }
|
| 432 |
+
|
| 433 |
+
|
| 434 |
@media (max-width: 768px) {
|
| 435 |
main { padding: 1.5rem; } h1 { font-size: 2.2rem; }
|
| 436 |
.aspect-ratio-selector { grid-template-columns: repeat(2, 1fr); }
|
|
|
|
| 483 |
<div class="ratio-icon" id="icon-landscape"><div></div></div>
|
| 484 |
<div class="ratio-label">افقی ۱۶:۹</div>
|
| 485 |
</div>
|
| 486 |
+
<div class="ratio-option" data-ratio="custom">
|
| 487 |
+
<div class="ratio-icon" id="icon-custom">
|
| 488 |
+
<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">
|
| 489 |
+
<path d="M21 16V8a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h8"/>
|
| 490 |
+
<circle cx="18" cy="18" r="3"/>
|
| 491 |
+
<path d="M18 15v-2"/><path d="M18 21v-2"/>
|
| 492 |
+
<path d="M15 18h-2"/><path d="M21 18h-2"/>
|
| 493 |
+
</svg>
|
| 494 |
+
</div>
|
| 495 |
+
<div class="ratio-label">
|
| 496 |
+
اندازه دلخواه
|
| 497 |
+
<div class="custom-ratio-value" id="custom-ratio-label-value"></div>
|
| 498 |
+
</div>
|
| 499 |
</div>
|
| 500 |
<div class="ratio-option active" data-ratio="1:1">
|
| 501 |
<div class="ratio-icon" id="icon-square"><div></div></div>
|
|
|
|
| 533 |
<div id="lora-grid"></div>
|
| 534 |
</div>
|
| 535 |
</div>
|
| 536 |
+
|
| 537 |
+
<!-- Modal for Custom Size -->
|
| 538 |
+
<div class="modal-overlay" id="custom-size-modal">
|
| 539 |
+
<div class="modal-content-small">
|
| 540 |
+
<button id="close-custom-modal-btn">×</button>
|
| 541 |
+
<h3>تنظیم اندازه دلخواه</h3>
|
| 542 |
+
<div class="input-group">
|
| 543 |
+
<label for="custom-width-input">عرض (Width)</label>
|
| 544 |
+
<input type="number" id="custom-width-input" value="1024" min="512" max="1536" step="8" placeholder="بین ۵۱۲ تا ۱۵۳۶">
|
| 545 |
+
</div>
|
| 546 |
+
<div class="input-group">
|
| 547 |
+
<label for="custom-height-input">طول (Height)</label>
|
| 548 |
+
<input type="number" id="custom-height-input" value="1024" min="512" max="1536" step="8" placeholder="بین ۵۱۲ تا ۱۵۳۶">
|
| 549 |
+
</div>
|
| 550 |
+
<button id="confirm-custom-size-btn">تایید و اعمال</button>
|
| 551 |
+
</div>
|
| 552 |
+
</div>
|
| 553 |
+
|
| 554 |
|
| 555 |
<script type="module">
|
| 556 |
import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
|
|
|
|
| 2285 |
const originalModalTitleHTML = modalTitle.innerHTML;
|
| 2286 |
let longPressTimer = null;
|
| 2287 |
let longPressJustHappened = false;
|
| 2288 |
+
|
| 2289 |
+
const customSizeModal = document.getElementById('custom-size-modal');
|
| 2290 |
+
const closeCustomModalBtn = document.getElementById('close-custom-modal-btn');
|
| 2291 |
+
const confirmCustomSizeBtn = document.getElementById('confirm-custom-size-btn');
|
| 2292 |
+
const customWidthInput = document.getElementById('custom-width-input');
|
| 2293 |
+
const customHeightInput = document.getElementById('custom-height-input');
|
| 2294 |
+
const customRatioLabel = document.getElementById('custom-ratio-label-value');
|
| 2295 |
|
| 2296 |
let selectedLora = null;
|
| 2297 |
let selectedRatio = '1:1';
|
| 2298 |
+
let customWidth = 1024;
|
| 2299 |
+
let customHeight = 1024;
|
| 2300 |
let imageObserver = null;
|
| 2301 |
let fluxClient = null;
|
| 2302 |
let countdownInterval = null;
|
|
|
|
| 2548 |
|
| 2549 |
setLoadingState(true, 'در حال پردازش...');
|
| 2550 |
const getDimensions = (ratio) => {
|
| 2551 |
+
if (ratio === 'custom') {
|
| 2552 |
+
return { width: customWidth, height: customHeight };
|
| 2553 |
+
}
|
| 2554 |
switch (ratio) {
|
| 2555 |
+
case '9:16': return { width: 768, height: 1344 };
|
| 2556 |
+
case '16:9': return { width: 1344, height: 768 };
|
|
|
|
| 2557 |
default: return { width: 1024, height: 1024 };
|
| 2558 |
}
|
| 2559 |
};
|
|
|
|
| 2670 |
ratioSelector.addEventListener('click', (event) => {
|
| 2671 |
const selectedOption = event.target.closest('.ratio-option');
|
| 2672 |
if (!selectedOption) return;
|
| 2673 |
+
const ratioValue = selectedOption.dataset.ratio;
|
| 2674 |
+
|
| 2675 |
+
if (ratioValue === 'custom') {
|
| 2676 |
+
customSizeModal.style.display = 'flex';
|
| 2677 |
+
} else {
|
| 2678 |
+
ratioSelector.querySelectorAll('.ratio-option').forEach(opt => opt.classList.remove('active'));
|
| 2679 |
+
selectedOption.classList.add('active');
|
| 2680 |
+
selectedRatio = ratioValue;
|
| 2681 |
+
}
|
| 2682 |
+
});
|
| 2683 |
+
|
| 2684 |
+
closeCustomModalBtn.addEventListener('click', () => {
|
| 2685 |
+
customSizeModal.style.display = 'none';
|
| 2686 |
+
});
|
| 2687 |
+
|
| 2688 |
+
customSizeModal.addEventListener('click', (event) => {
|
| 2689 |
+
if (event.target === customSizeModal) {
|
| 2690 |
+
customSizeModal.style.display = 'none';
|
| 2691 |
+
}
|
| 2692 |
+
});
|
| 2693 |
+
|
| 2694 |
+
confirmCustomSizeBtn.addEventListener('click', () => {
|
| 2695 |
+
const width = parseInt(customWidthInput.value, 10);
|
| 2696 |
+
const height = parseInt(customHeightInput.value, 10);
|
| 2697 |
+
|
| 2698 |
+
if (isNaN(width) || isNaN(height) || width < 512 || height < 512 || width > 1536 || height > 1536) {
|
| 2699 |
+
alert('مقادیر عرض و طول باید بین ۵۱۲ و ۱۵۳۶ پیکسل باشند.');
|
| 2700 |
+
return;
|
| 2701 |
+
}
|
| 2702 |
+
|
| 2703 |
+
if (width % 8 !== 0 || height % 8 !== 0) {
|
| 2704 |
+
alert('مقادیر عرض و طول باید بر ۸ بخشپذیر باشند.');
|
| 2705 |
+
return;
|
| 2706 |
+
}
|
| 2707 |
+
|
| 2708 |
+
customWidth = width;
|
| 2709 |
+
customHeight = height;
|
| 2710 |
+
selectedRatio = 'custom';
|
| 2711 |
+
|
| 2712 |
ratioSelector.querySelectorAll('.ratio-option').forEach(opt => opt.classList.remove('active'));
|
| 2713 |
+
document.querySelector('.ratio-option[data-ratio="custom"]').classList.add('active');
|
| 2714 |
+
|
| 2715 |
+
customRatioLabel.textContent = `${width} x ${height}`;
|
| 2716 |
+
customSizeModal.style.display = 'none';
|
| 2717 |
});
|
| 2718 |
|
| 2719 |
clearResult();
|