mirror of
https://github.com/yusufipk/imagen-openrouter.git
synced 2026-09-11 10:36:07 +00:00
feat: add reference and recreate buttons to image cards with corresponding styles
This commit is contained in:
+88
-1
@@ -876,7 +876,7 @@ function renderGallery() {
|
|||||||
const safePrompt = escapeHtml(image.prompt);
|
const safePrompt = escapeHtml(image.prompt);
|
||||||
|
|
||||||
card.innerHTML = `
|
card.innerHTML = `
|
||||||
<div class="image-card-actions">
|
<div class="image-card-actions image-card-actions-top">
|
||||||
<button class="image-card-btn image-card-download" data-index="${index}" title="Download image">
|
<button class="image-card-btn image-card-download" data-index="${index}" title="Download image">
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
||||||
@@ -893,6 +893,21 @@ function renderGallery() {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="image-card-actions image-card-actions-bottom">
|
||||||
|
<button class="image-card-btn image-card-reference" data-index="${index}" title="Use as reference">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
|
||||||
|
<circle cx="12" cy="10" r="3"></circle>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="image-card-btn image-card-recreate" data-index="${index}" title="Recreate with same settings">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<polyline points="23 4 23 10 17 10"></polyline>
|
||||||
|
<polyline points="1 20 1 14 7 14"></polyline>
|
||||||
|
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<img src="${safeUrl}" alt="${safePrompt}" loading="lazy">
|
<img src="${safeUrl}" alt="${safePrompt}" loading="lazy">
|
||||||
<div class="image-card-overlay">
|
<div class="image-card-overlay">
|
||||||
<p class="image-card-prompt">${safePrompt}</p>
|
<p class="image-card-prompt">${safePrompt}</p>
|
||||||
@@ -918,6 +933,20 @@ function renderGallery() {
|
|||||||
deleteImage(index);
|
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
|
// Open modal on card click
|
||||||
card.addEventListener('click', () => openModal(image));
|
card.addEventListener('click', () => openModal(image));
|
||||||
elements.gallery.appendChild(card);
|
elements.gallery.appendChild(card);
|
||||||
@@ -952,6 +981,64 @@ function downloadImageByIndex(index) {
|
|||||||
showToast('Image downloaded', 'success');
|
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 =====
|
// ===== Modal =====
|
||||||
function openModal(image) {
|
function openModal(image) {
|
||||||
state.currentImage = image;
|
state.currentImage = image;
|
||||||
|
|||||||
+22
-2
@@ -757,13 +757,21 @@ body {
|
|||||||
|
|
||||||
.image-card-actions {
|
.image-card-actions {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10px;
|
|
||||||
right: 10px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-card-actions-top {
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-card-actions-bottom {
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.image-card-btn {
|
.image-card-btn {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@@ -800,6 +808,18 @@ body {
|
|||||||
transform: scale(1.1);
|
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 {
|
.image-card-prompt {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
|
|||||||
Reference in New Issue
Block a user