() => { function init() { if (window.__fireRedInitDone) 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 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.__fireRedInitDone = true; let images = []; window.__uploadedImages = images; let selectedIdx = -1; let toastTimer = null; 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'); if (type === 'warning') icon.textContent = '⚠'; else if (type === 'info') icon.textContent = 'ℹ'; else icon.textContent = '✗'; 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 updateCounts() { const n = images.length; const txt = n > 0 ? n + ' image' + (n > 1 ? 's' : '') : 'No images'; if (imgCountTb) imgCountTb.textContent = txt; if (imgCountSb) imgCountSb.textContent = n > 0 ? txt + ' uploaded' : 'No images uploaded'; } function addImage(b64, name) { images.push({id: Date.now() + Math.random(), b64: b64, name: name}); renderGallery(); syncImagesToGradio(); } window.__addImage = addImage; function removeImage(idx) { images.splice(idx, 1); if (selectedIdx === idx) selectedIdx = -1; else if (selectedIdx > idx) selectedIdx--; renderGallery(); syncImagesToGradio(); } function clearAll() { images = []; window.__uploadedImages = images; selectedIdx = -1; renderGallery(); syncImagesToGradio(); } window.__clearAll = clearAll; function selectImage(idx) { selectedIdx = (selectedIdx === idx) ? -1 : idx; renderGallery(); } function renderGallery() { if (images.length === 0) { galleryGrid.innerHTML = ''; galleryGrid.style.display = 'none'; if (uploadPrompt) uploadPrompt.style.display = ''; return; } if (uploadPrompt) uploadPrompt.style.display = 'none'; galleryGrid.style.display = 'grid'; let html = ''; images.forEach((img, i) => { const sel = i === selectedIdx ? ' selected' : ''; html += ''; }); html += ''; galleryGrid.innerHTML = html; galleryGrid.querySelectorAll('.gallery-thumb').forEach(thumb => { thumb.addEventListener('click', (e) => { if (e.target.closest('.thumb-remove')) return; selectImage(parseInt(thumb.dataset.idx)); }); }); 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()); } function processFiles(files) { Array.from(files).forEach(file => { if (!file.type.startsWith('image/')) return; const reader = new FileReader(); reader.onload = (e) => addImage(e.target.result, file.name); reader.readAsDataURL(file); }); } 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 && selectedIdx < images.length) 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', (e) => { if (!e.isComposing) syncPromptToGradio(); }); window.__setPrompt = function(text) { if (promptInput) { promptInput.value = text; syncPromptToGradio(); } }; 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...', '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'); syncSlider('custom-gpu-duration', 'gradio-gpu-duration'); 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...'; } 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(); 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(); }