() => { function init() { if (window.__qwenInitDone) return; // Dual-skin: ensure boot ran (HF load order can race). Removes unused shell. if (typeof window.__qwenActivateUiSkin === 'function' && !window.__qwenUiSkin) { window.__qwenActivateUiSkin(); } if (!window.__qwenUiSkin) { const dual = document.getElementById('skin-desktop') || document.getElementById('skin-phone'); if (dual) { setTimeout(init, 50); return; } } const galleryGrid = document.getElementById('image-gallery-grid'); const dropZone = document.getElementById('gallery-drop-zone'); const uploadPrompt = document.getElementById('upload-prompt'); const uploadClick = document.getElementById('upload-click-area'); const fileInput = document.getElementById('custom-file-input'); const btnUpload = document.getElementById('tb-upload'); const btnRemove = document.getElementById('tb-remove'); const btnClear = document.getElementById('tb-clear'); const promptInput = document.getElementById('custom-prompt-input'); const loraSelect = document.getElementById('custom-lora-select'); const packSelect = document.getElementById('custom-prompt-pack-select'); const aspectSelect = document.getElementById('custom-aspect-select'); const sizeSelect = document.getElementById('custom-size-select'); const runBtnEl = document.getElementById('custom-run-btn'); const imgCountTb = document.getElementById('tb-image-count'); const imgCountSb = document.getElementById('sb-image-count'); if (!galleryGrid || !fileInput || !dropZone) { setTimeout(init, 250); return; } window.__qwenInitDone = true; // HF: re-pin floating Edit after UI is live (transform ancestors break fixed) if (typeof window.__qwenPinPhoneRunBar === 'function') { window.__qwenPinPhoneRunBar(); setTimeout(window.__qwenPinPhoneRunBar, 300); } window.__toggleAdvancedSettings = function() { const group = document.getElementById('advanced-settings'); const toggle = document.getElementById('advanced-settings-toggle'); if (!group) return; const open = group.classList.toggle('open'); if (toggle) toggle.setAttribute('aria-expanded', open ? 'true' : 'false'); }; let images = []; window.__uploadedImages = images; let selectedIdx = -1; let toastTimer = null; const IMAGE_SIZE_BASE = {'x-small':512,'small':768,'normal':1024,'large':1280,'x-large':1536}; const MAX_SOURCE_SIDE = 4000; const SIZE_LABELS = { original: 'Original (source pixels)', 'x-small': 'X-Small (thumbnail)', small: 'Small', normal: 'Normal', large: 'Large', 'x-large': 'X-Large', }; function round8(n) { return Math.max(8, Math.floor(Number(n) / 8) * 8); } function capSourceDims(w, h) { const longSide = Math.max(w, h); if (!longSide || longSide <= MAX_SOURCE_SIDE) return [w, h]; const s = MAX_SOURCE_SIDE / longSide; return [Math.max(1, Math.round(w * s)), Math.max(1, Math.round(h * s))]; } function computeOutputDims(srcW, srcH, aspect, size) { if (!srcW || !srcH) return null; if (size === 'original') { let [w, h] = capSourceDims(srcW, srcH); const longSide = Math.max(w, h); if (aspect === 'square') return [round8(longSide), round8(longSide)]; if (aspect === 'wide') return [round8(longSide), round8(longSide * 9 / 16)]; if (aspect === 'portrait') return [round8(longSide * 9 / 16), round8(longSide)]; return [round8(w), round8(h)]; } const base = IMAGE_SIZE_BASE[size] || 1024; const scale = base / 1024; if (aspect === 'square') return [round8(base), round8(base)]; if (aspect === 'wide') return [round8(1344 * scale), round8(768 * scale)]; if (aspect === 'portrait') return [round8(768 * scale), round8(1344 * scale)]; if (srcW >= srcH) { const tw = base; return [round8(tw), round8(tw * srcH / srcW)]; } const th = base; return [round8(th * srcW / srcH), round8(th)]; } function formatDims(w, h) { return w + ' \u00d7 ' + h; } function getAspect() { return aspectSelect ? aspectSelect.value : 'original'; } function getSize() { return sizeSelect ? sizeSelect.value : 'normal'; } function updatePredictedSizeUI() { const outEl = document.getElementById('output-pred-dims'); const sizeEl = document.getElementById('size-pred-dims'); const first = images.length ? images[0] : null; const srcW = first && first.w ? first.w : 0; const srcH = first && first.h ? first.h : 0; const hasSrc = srcW > 0 && srcH > 0; const aspect = getAspect(); const size = getSize(); // Dynamic size-menu labels (show predicted W×H when image #1 is known) if (sizeSelect) { Array.from(sizeSelect.options).forEach(opt => { const key = opt.value; const baseLabel = SIZE_LABELS[key] || key; if (!hasSrc) { if (key === 'original') opt.textContent = baseLabel; else if (key === 'x-small') opt.textContent = 'X-Small (thumbnail \u00b7 512)'; else if (key === 'small') opt.textContent = 'Small (768)'; else if (key === 'normal') opt.textContent = 'Normal (1024)'; else if (key === 'large') opt.textContent = 'Large (1280)'; else if (key === 'x-large') opt.textContent = 'X-Large (1536)'; else opt.textContent = baseLabel; return; } const dims = computeOutputDims(srcW, srcH, aspect, key); if (dims) opt.textContent = baseLabel + ' \u2014 ' + formatDims(dims[0], dims[1]); else opt.textContent = baseLabel; }); } if (!hasSrc) { if (outEl) { outEl.hidden = true; outEl.textContent = ''; } if (sizeEl) { sizeEl.hidden = true; sizeEl.textContent = ''; } return; } const pred = computeOutputDims(srcW, srcH, aspect, size); if (!pred) return; const txt = formatDims(pred[0], pred[1]); if (outEl) { outEl.hidden = false; outEl.textContent = txt; } if (sizeEl) { sizeEl.hidden = false; sizeEl.textContent = 'Predicted output: ' + txt + (size === 'original' && Math.max(srcW, srcH) > MAX_SOURCE_SIDE ? ' (source capped at ' + MAX_SOURCE_SIDE + ' long side)' : ''); } } /* ── Force dark + blue styles on elements that browsers may override ── */ function enforceDarkStyles() { document.querySelectorAll('.lora-selector-card').forEach(el => { el.style.setProperty('background','#0f0f13','important'); }); document.querySelectorAll('.lora-selector-body').forEach(el => { el.style.setProperty('background','#0f0f13','important'); }); document.querySelectorAll('.lora-select-label').forEach(el => { el.style.setProperty('color','#71717a','important'); el.style.setProperty('-webkit-text-fill-color','#71717a','important'); }); [ document.getElementById('custom-lora-select'), document.getElementById('custom-aspect-select'), document.getElementById('custom-size-select'), ].forEach(sel => { if (!sel) return; sel.style.setProperty('background-color','#09090b','important'); sel.style.setProperty('color','#e4e4e7','important'); sel.style.setProperty('-webkit-text-fill-color','#e4e4e7','important'); sel.style.setProperty('border-color','#3f3f46','important'); }); const ghBtn = document.querySelector('.gh-btn'); if (ghBtn) { ghBtn.style.setProperty('background','#1E90FF','important'); ghBtn.style.setProperty('color','#ffffff','important'); ghBtn.style.setProperty('-webkit-text-fill-color','#ffffff','important'); ghBtn.style.setProperty('border-color','rgba(255,255,255,.18)','important'); ghBtn.style.setProperty('box-shadow','0 2px 10px rgba(30,144,255,.45)','important'); const svg = ghBtn.querySelector('svg'); if (svg) svg.style.setProperty('fill','#ffffff','important'); const span = ghBtn.querySelector('span'); if (span) { span.style.setProperty('color','#ffffff','important'); span.style.setProperty('-webkit-text-fill-color','#ffffff','important'); } } const shell = document.querySelector('.app-shell'); const header = document.querySelector('.app-header'); const toolbar = document.querySelector('.app-toolbar'); if (shell) shell.style.setProperty('background','#18181b','important'); if (header) header.style.setProperty('background','#18181b','important'); if (toolbar) toolbar.style.setProperty('background','#18181b','important'); } enforceDarkStyles(); setInterval(enforceDarkStyles, 1000); const ghBtn = document.querySelector('.gh-btn'); if (ghBtn) { ghBtn.addEventListener('mouseenter', () => { ghBtn.style.setProperty('background','#47A3FF','important'); ghBtn.style.setProperty('color','#ffffff','important'); ghBtn.style.setProperty('-webkit-text-fill-color','#ffffff','important'); ghBtn.style.setProperty('transform','translateY(-1px)','important'); ghBtn.style.setProperty('box-shadow','0 5px 18px rgba(30,144,255,.6)','important'); }); ghBtn.addEventListener('mouseleave', () => { ghBtn.style.setProperty('background','#1E90FF','important'); ghBtn.style.setProperty('color','#ffffff','important'); ghBtn.style.setProperty('-webkit-text-fill-color','#ffffff','important'); ghBtn.style.setProperty('transform','translateY(0)','important'); ghBtn.style.setProperty('box-shadow','0 2px 10px rgba(30,144,255,.45)','important'); }); ghBtn.addEventListener('mousedown', () => { ghBtn.style.setProperty('background','#1873CC','important'); ghBtn.style.setProperty('transform','translateY(0)','important'); }); ghBtn.addEventListener('mouseup', () => { ghBtn.style.setProperty('background','#47A3FF','important'); }); } function showToast(message, type) { let toast = document.getElementById('app-toast'); if (!toast) { toast = document.createElement('div'); toast.id = 'app-toast'; toast.className = 'toast-notification'; toast.innerHTML = ''; document.body.appendChild(toast); } const icon = toast.querySelector('.toast-icon'); const text = toast.querySelector('.toast-text'); toast.className = 'toast-notification ' + (type || 'error'); icon.textContent = type === 'warning' ? '\u26A0' : type === 'info' ? '\u2139' : '\u2717'; text.textContent = message; if (toastTimer) clearTimeout(toastTimer); void toast.offsetWidth; toast.classList.add('visible'); toastTimer = setTimeout(() => toast.classList.remove('visible'), 3500); } window.__showToast = showToast; function flashPromptError() { if (!promptInput) return; promptInput.classList.add('error-flash'); promptInput.focus(); setTimeout(() => promptInput.classList.remove('error-flash'), 800); } function setGradioValue(containerId, value) { const container = document.getElementById(containerId); if (!container) return; container.querySelectorAll('input, textarea').forEach(el => { if (el.type === 'file' || el.type === 'range' || el.type === 'checkbox') return; const proto = el.tagName === 'TEXTAREA' ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype; const ns = Object.getOwnPropertyDescriptor(proto, 'value'); if (ns && ns.set) { ns.set.call(el, value); el.dispatchEvent(new Event('input', {bubbles:true, composed:true})); el.dispatchEvent(new Event('change', {bubbles:true, composed:true})); } }); } window.__setGradioValue = setGradioValue; function syncImagesToGradio() { window.__uploadedImages = images; const b64Array = images.map(img => img.b64); setGradioValue('hidden-images-b64', JSON.stringify(b64Array)); updateCounts(); } function syncPromptToGradio() { if (promptInput) setGradioValue('prompt-gradio-input', promptInput.value); } function syncLoraToGradio() { if (!loraSelect) return; const container = document.getElementById('gradio-lora'); if (!container) return; container.querySelectorAll('input').forEach(el => { const ns = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); if (ns && ns.set) { ns.set.call(el, loraSelect.value); el.dispatchEvent(new Event('input', {bubbles:true, composed:true})); el.dispatchEvent(new Event('change', {bubbles:true, composed:true})); } }); } function syncPromptPackToGradio() { if (!packSelect) return; const container = document.getElementById('gradio-prompt-pack'); if (!container) return; container.querySelectorAll('input').forEach(el => { const ns = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); if (ns && ns.set) { ns.set.call(el, packSelect.value); el.dispatchEvent(new Event('input', {bubbles:true, composed:true})); el.dispatchEvent(new Event('change', {bubbles:true, composed:true})); } }); } function syncAspectToGradio() { if (!aspectSelect) return; const container = document.getElementById('gradio-aspect'); if (!container) return; container.querySelectorAll('input').forEach(el => { const ns = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); if (ns && ns.set) { ns.set.call(el, aspectSelect.value); el.dispatchEvent(new Event('input', {bubbles:true, composed:true})); el.dispatchEvent(new Event('change', {bubbles:true, composed:true})); } }); } function syncSizeToGradio() { if (!sizeSelect) return; const container = document.getElementById('gradio-size'); if (!container) return; container.querySelectorAll('input').forEach(el => { const ns = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); if (ns && ns.set) { ns.set.call(el, sizeSelect.value); el.dispatchEvent(new Event('input', {bubbles:true, composed:true})); el.dispatchEvent(new Event('change', {bubbles:true, composed:true})); } }); } const MAX_IMAGES = 2; function updateCounts() { const n = images.length; const txt = n > 0 ? n + ' image' + (n > 1 ? 's' : '') + ' (max ' + MAX_IMAGES + ')' : 'No images'; if (imgCountTb) imgCountTb.textContent = n > 0 ? n + ' image' + (n > 1 ? 's' : '') : 'No images'; if (imgCountSb) imgCountSb.textContent = n > 0 ? n + ' / ' + MAX_IMAGES + ' images' : 'No images uploaded'; } function addImage(b64, name) { if (images.length >= MAX_IMAGES) { showToast('Maximum ' + MAX_IMAGES + ' images. Remove one to add another.', 'warning'); return false; } const entry = {id: Date.now() + Math.random(), b64, name, w: 0, h: 0}; images.push(entry); renderGallery(); syncImagesToGradio(); updatePredictedSizeUI(); const probe = new Image(); probe.onload = () => { entry.w = probe.naturalWidth || 0; entry.h = probe.naturalHeight || 0; renderGallery(); updatePredictedSizeUI(); }; probe.onerror = () => { updatePredictedSizeUI(); }; probe.src = b64; return true; } window.__addImage = addImage; function removeImage(idx) { images.splice(idx, 1); if (selectedIdx === idx) selectedIdx = -1; else if (selectedIdx > idx) selectedIdx--; renderGallery(); syncImagesToGradio(); updatePredictedSizeUI(); } function clearAll() { images = []; window.__uploadedImages = images; selectedIdx = -1; renderGallery(); syncImagesToGradio(); updatePredictedSizeUI(); } window.__clearAll = clearAll; function renderGallery() { if (images.length === 0) { galleryGrid.innerHTML = ''; galleryGrid.style.display = 'none'; if (uploadPrompt) uploadPrompt.style.display = ''; updatePredictedSizeUI(); updateCounts(); return; } if (uploadPrompt) uploadPrompt.style.display = 'none'; galleryGrid.style.display = 'grid'; let html = ''; images.forEach((img, i) => { const sel = i === selectedIdx ? ' selected' : ''; const dimTxt = (img.w && img.h) ? formatDims(img.w, img.h) : '\u2026'; const role = i === 0 ? 'Main' : 'Ref'; html += ''; }); if (images.length < MAX_IMAGES) { html += ''; } galleryGrid.innerHTML = html; galleryGrid.querySelectorAll('.gallery-thumb').forEach(thumb => { thumb.addEventListener('click', (e) => { if (e.target.closest('.thumb-remove')) return; selectedIdx = (selectedIdx === parseInt(thumb.dataset.idx)) ? -1 : parseInt(thumb.dataset.idx); renderGallery(); }); }); galleryGrid.querySelectorAll('.thumb-remove').forEach(btn => { btn.addEventListener('click', (e) => { e.stopPropagation(); removeImage(parseInt(btn.dataset.remove)); }); }); const addCard = document.getElementById('gallery-add-card'); if (addCard) addCard.addEventListener('click', () => fileInput.click()); updateCounts(); } function processFiles(files) { const list = Array.from(files).filter(f => f && f.type && f.type.startsWith('image/')); if (!list.length) return; let skipped = 0; list.forEach(file => { if (images.length >= MAX_IMAGES) { skipped++; return; } const reader = new FileReader(); reader.onload = (e) => addImage(e.target.result, file.name); reader.readAsDataURL(file); }); if (skipped > 0) { showToast('Maximum ' + MAX_IMAGES + ' images. Extra file(s) were not added.', 'warning'); } } fileInput.addEventListener('change', (e) => { processFiles(e.target.files); e.target.value = ''; }); if (uploadClick) uploadClick.addEventListener('click', () => fileInput.click()); if (btnUpload) btnUpload.addEventListener('click', () => fileInput.click()); if (btnRemove) btnRemove.addEventListener('click', () => { if (selectedIdx >= 0) removeImage(selectedIdx); }); if (btnClear) btnClear.addEventListener('click', clearAll); dropZone.addEventListener('dragover', (e) => { e.preventDefault(); dropZone.classList.add('drag-over'); }); dropZone.addEventListener('dragleave', (e) => { e.preventDefault(); dropZone.classList.remove('drag-over'); }); dropZone.addEventListener('drop', (e) => { e.preventDefault(); dropZone.classList.remove('drag-over'); if (e.dataTransfer.files.length) processFiles(e.dataTransfer.files); }); if (promptInput) promptInput.addEventListener('input', syncPromptToGradio); if (loraSelect) loraSelect.addEventListener('change', () => { // Original path: sync Gradio; lora_demo.js also listens and updates before/after demos syncLoraToGradio(); if (window.__setLoraDemos) window.__setLoraDemos(loraSelect.value); }); if (window.__setLoraDemos) setTimeout(() => window.__setLoraDemos(loraSelect ? loraSelect.value : 'none'), 300); function updatePromptPackDescription() { const descEl = document.getElementById('prompt-pack-desc'); if (!descEl || !packSelect) return; const opt = packSelect.options[packSelect.selectedIndex]; const raw = (opt && opt.getAttribute('data-description')) || ''; const fallbackNone = 'Prompt Packs add variety the base model struggles with in specific areas. Choose a pack in the menu below, or trigger one in the prompt (e.g. [[pack]]).'; descEl.textContent = raw.trim() || ( !packSelect.value || packSelect.value === 'none' ? fallbackNone : ('Pack "' + packSelect.value + '" will apply on Run (menu overrides prompt tags).') ); } if (packSelect) { packSelect.addEventListener('change', () => { syncPromptPackToGradio(); updatePromptPackDescription(); }); updatePromptPackDescription(); } if (aspectSelect) aspectSelect.addEventListener('change', () => { syncAspectToGradio(); updatePredictedSizeUI(); }); if (sizeSelect) sizeSelect.addEventListener('change', () => { syncSizeToGradio(); updatePredictedSizeUI(); }); updatePredictedSizeUI(); /* ── Toggle quick-prompt chips (amend / remove) ── */ const activeChips = new Map(); const CAMERA_MUTEX_GROUPS = [ ['45-right', '45-left'], ['front-right', 'front-left', 'back-right', 'back-left'], ['profile-right', 'profile-left'], ['zoom-in', 'zoom-out'], ['top-down', 'low-angle'], ]; function normalizeSpaces(s) { return (s || '').replace(/[ \t]+/g, ' ').replace(/\n{3,}/g, '\n\n').trim(); } function appendPhrase(phrase) { if (!promptInput) return; let cur = promptInput.value || ''; const p = (phrase || '').trim(); if (!p) return; if (!cur.trim()) promptInput.value = p; else { const needsSpace = !/\s$/.test(cur); promptInput.value = cur + (needsSpace ? ' ' : '') + p; } syncPromptToGradio(); } function removePhrase(phrase) { if (!promptInput) return; const p = (phrase || '').trim(); if (!p) return; const re = new RegExp('\\s*' + p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\s*', 'g'); promptInput.value = normalizeSpaces((promptInput.value || '').replace(re, ' ')); syncPromptToGradio(); } function cameraMutexPeers(chipId) { for (const group of CAMERA_MUTEX_GROUPS) { if (group.includes(chipId)) return group.filter(id => id !== chipId); } return []; } function deactivateChipById(chipId) { const btn = document.querySelector('.suggestion-chip[data-chip-id="' + chipId + '"]'); if (!btn || !btn.classList.contains('active')) return; const phrase = activeChips.get(chipId) || btn.getAttribute('data-prompt') || ''; if (phrase) removePhrase(phrase); btn.classList.remove('active'); activeChips.delete(chipId); } function wireChips(root, opts) { opts = opts || {}; if (!root) return; root.querySelectorAll('.suggestion-chip[data-prompt]').forEach(btn => { btn.addEventListener('click', () => { const id = btn.getAttribute('data-chip-id') || btn.textContent.trim(); const phrase = btn.getAttribute('data-prompt') || ''; if (btn.classList.contains('active')) { removePhrase(phrase); btn.classList.remove('active'); activeChips.delete(id); showToast('Removed from prompt', 'info'); } else { if (opts.cameraMutex) cameraMutexPeers(id).forEach(deactivateChipById); appendPhrase(phrase); btn.classList.add('active'); activeChips.set(id, phrase); showToast('Added to prompt', 'info'); } }); }); } wireChips(document.getElementById('style-chips')); wireChips(document.getElementById('camera-chips'), { cameraMutex: true }); wireChips(document.getElementById('lora-chips')); /* ── Per-panel chip toolbars + master Open/Close + Clear Prompts ── */ const CHIP_HINT = '(click to add · again to remove)'; const chipPanels = Array.from(document.querySelectorAll('.chip-panel[data-panel]')); const btnOpenPrompts = document.getElementById('tb-open-prompts'); const btnOpenPromptsLabel = document.getElementById('tb-open-prompts-label'); const btnClearPrompts = document.getElementById('tb-clear-prompts'); function setPanelOpen(panel, open) { if (!panel) return; const toggle = panel.querySelector('.chip-panel-toolbar'); const body = panel.querySelector('.chip-panel-body'); const hint = panel.querySelector('.chip-panel-hint'); panel.classList.toggle('open', open); if (body) body.hidden = !open; if (toggle) { toggle.setAttribute('aria-expanded', open ? 'true' : 'false'); // Closed: full hint as native tooltip. Open: clear title so visible hint is the instruction. toggle.title = open ? '' : CHIP_HINT; } if (hint) hint.hidden = !open; } function isPanelOpen(panel) { return panel && panel.classList.contains('open'); } function anyPanelOpen() { return chipPanels.some(isPanelOpen); } function allPanelsOpen() { return chipPanels.length > 0 && chipPanels.every(isPanelOpen); } function syncMasterOpenButton() { const open = allPanelsOpen(); if (btnOpenPrompts) { btnOpenPrompts.setAttribute('aria-expanded', open ? 'true' : 'false'); btnOpenPrompts.classList.toggle('active', open || anyPanelOpen()); } if (btnOpenPromptsLabel) { const phone = window.__qwenUiSkin === 'phone'; btnOpenPromptsLabel.textContent = open ? (phone ? 'Close' : 'Close Prompts') : (phone ? 'Open' : 'Open Prompts'); } } function setAllPanelsOpen(open) { chipPanels.forEach(p => setPanelOpen(p, open)); syncMasterOpenButton(); } chipPanels.forEach(panel => { const toggle = panel.querySelector('.chip-panel-toolbar'); if (!toggle) return; setPanelOpen(panel, false); // start closed; title bar always visible toggle.addEventListener('click', () => { setPanelOpen(panel, !isPanelOpen(panel)); syncMasterOpenButton(); }); }); if (btnOpenPrompts) { btnOpenPrompts.addEventListener('click', () => { // If all open → close all; otherwise open all setAllPanelsOpen(!allPanelsOpen()); }); } syncMasterOpenButton(); function clearPromptsOnly() { if (promptInput) { promptInput.value = ''; syncPromptToGradio(); } document.querySelectorAll('.suggestion-chip.active').forEach(btn => btn.classList.remove('active')); activeChips.clear(); showToast('Prompt cleared', 'info'); } if (btnClearPrompts) btnClearPrompts.addEventListener('click', clearPromptsOnly); window.__clearPrompts = clearPromptsOnly; window.__setPromptsOpen = setAllPanelsOpen; window.__setPanelOpen = setPanelOpen; window.__setPrompt = function(text) { if (promptInput) { promptInput.value = text; syncPromptToGradio(); } }; window.__setLora = function(lora) { if (loraSelect) { loraSelect.value = lora || 'none'; loraSelect.dispatchEvent(new Event('change', {bubbles:true})); syncLoraToGradio(); if (window.__setLoraDemos) window.__setLoraDemos(loraSelect.value); } }; window.__setAspect = function(aspect) { if (aspectSelect) { aspectSelect.value = aspect; aspectSelect.dispatchEvent(new Event('change', {bubbles:true})); syncAspectToGradio(); } }; window.__setSize = function(size) { if (sizeSelect) { sizeSelect.value = size; sizeSelect.dispatchEvent(new Event('change', {bubbles:true})); syncSizeToGradio(); } }; document.querySelectorAll('.example-card[data-idx]').forEach(card => { card.addEventListener('click', () => { const idx = card.getAttribute('data-idx'); document.querySelectorAll('.example-card.loading').forEach(c => c.classList.remove('loading')); card.classList.add('loading'); showToast('Loading example\u2026', 'info'); setGradioValue('example-result-data', ''); setGradioValue('example-idx-input', idx); setTimeout(() => { const btn = document.getElementById('example-load-btn'); if (btn) { const b = btn.querySelector('button'); if (b) b.click(); else btn.click(); } }, 150); setTimeout(() => card.classList.remove('loading'), 12000); }); }); function syncSlider(customId, gradioId) { const slider = document.getElementById(customId); const valSpan = document.getElementById(customId + '-val'); if (!slider) return; slider.addEventListener('input', () => { if (valSpan) valSpan.textContent = slider.value; const container = document.getElementById(gradioId); if (!container) return; container.querySelectorAll('input[type="range"],input[type="number"]').forEach(el => { const ns = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); if (ns && ns.set) { ns.set.call(el, slider.value); el.dispatchEvent(new Event('input', {bubbles:true, composed:true})); el.dispatchEvent(new Event('change', {bubbles:true, composed:true})); } }); }); } syncSlider('custom-seed', 'gradio-seed'); syncSlider('custom-guidance', 'gradio-guidance'); syncSlider('custom-steps', 'gradio-steps'); const randCheck = document.getElementById('custom-randomize'); if (randCheck) { randCheck.addEventListener('change', () => { const container = document.getElementById('gradio-randomize'); if (!container) return; const cb = container.querySelector('input[type="checkbox"]'); if (cb && cb.checked !== randCheck.checked) cb.click(); }); } function showLoader() { const l = document.getElementById('output-loader'); if (l) l.classList.add('active'); const sb = document.querySelector('.sb-fixed'); if (sb) sb.textContent = 'Processing\u2026'; } function hideLoader() { const l = document.getElementById('output-loader'); if (l) l.classList.remove('active'); const sb = document.querySelector('.sb-fixed'); if (sb) sb.textContent = 'Done'; } window.__showLoader = showLoader; window.__hideLoader = hideLoader; function validateBeforeRun() { const promptVal = promptInput ? promptInput.value.trim() : ''; const hasImages = images.length > 0; if (!hasImages && !promptVal) { showToast('Please upload an image and enter a prompt', 'error'); flashPromptError(); return false; } if (!hasImages) { showToast('Please upload at least one image', 'error'); return false; } if (!promptVal) { showToast('Please enter an edit prompt', 'warning'); flashPromptError(); return false; } return true; } window.__clickGradioRunBtn = function() { if (!validateBeforeRun()) return; syncPromptToGradio(); syncImagesToGradio(); syncLoraToGradio(); syncPromptPackToGradio(); syncAspectToGradio(); syncSizeToGradio(); showLoader(); setTimeout(() => { const gradioBtn = document.getElementById('gradio-run-btn'); if (!gradioBtn) return; const btn = gradioBtn.querySelector('button'); if (btn) btn.click(); else gradioBtn.click(); }, 200); }; if (runBtnEl) runBtnEl.addEventListener('click', () => window.__clickGradioRunBtn()); renderGallery(); updateCounts(); } init(); }