diff --git a/src/app.js b/src/app.js index f9faed8..1d046b3 100644 --- a/src/app.js +++ b/src/app.js @@ -876,7 +876,7 @@ function renderGallery() { const safePrompt = escapeHtml(image.prompt); card.innerHTML = ` -
+
+
+ + +
${safePrompt}

${safePrompt}

@@ -918,6 +933,20 @@ function renderGallery() { deleteImage(index); }); + // Reference button handler + const referenceBtn = card.querySelector('.image-card-reference'); + referenceBtn.addEventListener('click', (e) => { + e.stopPropagation(); + addImageAsReference(index); + }); + + // Recreate button handler + const recreateBtn = card.querySelector('.image-card-recreate'); + recreateBtn.addEventListener('click', (e) => { + e.stopPropagation(); + recreateImageByIndex(index); + }); + // Open modal on card click card.addEventListener('click', () => openModal(image)); elements.gallery.appendChild(card); @@ -952,6 +981,64 @@ function downloadImageByIndex(index) { showToast('Image downloaded', 'success'); } +function addImageAsReference(index) { + const image = state.images[index]; + if (!image) return; + + state.references.push(image.url); + renderReferenceSlots(); + showToast('Image added as reference', 'success'); +} + +function recreateImageByIndex(index) { + const image = state.images[index]; + if (!image) return; + + // Restore prompt + elements.promptInput.value = image.prompt; + elements.charCount.textContent = `${image.prompt.length} chars`; + + // Restore model using custom select + state.selectedModel = image.model; + localStorage.setItem('imagen_model', state.selectedModel); + const modelOption = document.querySelector(`.custom-select-option[data-value="${image.model}"]`); + if (modelOption) { + document.querySelectorAll('.custom-select-option').forEach(o => o.classList.remove('selected')); + modelOption.classList.add('selected'); + elements.modelSelectValue.textContent = modelOption.textContent; + } + updateGeminiOptionsVisibility(); + + // Restore quality/size + document.querySelectorAll('.btn-toggle').forEach(btn => { + btn.classList.remove('active'); + if (btn.dataset.quality === image.quality) { + btn.classList.add('active'); + } + }); + + // Restore aspect ratio + document.querySelectorAll('.btn-aspect').forEach(btn => { + btn.classList.remove('active'); + if (btn.dataset.ratio === image.aspectRatio) { + btn.classList.add('active'); + } + }); + + // Restore references + if (image.references && image.references.length > 0) { + state.references = [...image.references]; + } else { + state.references = []; + } + renderReferenceSlots(); + + showToast('Settings restored. Click Generate to recreate.', 'success'); + + // Scroll to top + window.scrollTo({ top: 0, behavior: 'smooth' }); +} + // ===== Modal ===== function openModal(image) { state.currentImage = image; diff --git a/src/styles.css b/src/styles.css index fd92783..e577453 100644 --- a/src/styles.css +++ b/src/styles.css @@ -757,13 +757,21 @@ body { .image-card-actions { position: absolute; - top: 10px; - right: 10px; display: flex; gap: 8px; z-index: 10; } +.image-card-actions-top { + top: 10px; + right: 10px; +} + +.image-card-actions-bottom { + bottom: 10px; + right: 10px; +} + .image-card-btn { width: 32px; height: 32px; @@ -800,6 +808,18 @@ body { transform: scale(1.1); } +.image-card-reference:hover { + background: var(--success); + border-color: var(--success); + transform: scale(1.1); +} + +.image-card-recreate:hover { + background: #6366f1; + border-color: #6366f1; + transform: scale(1.1); +} + .image-card-prompt { font-size: 0.8rem; color: var(--text-primary);