mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-24 06:32:12 -03:00
Refactor recipe management to enhance initialization and metadata handling. Improve error logging during cache pre-warming, streamline recipe data structure, and ensure proper handling of generation parameters. Update UI components for missing LoRAs with improved summary and toggle functionality. Add new methods for adding recipes to cache and loading recipe data from JSON files.
This commit is contained in:
@@ -395,26 +395,77 @@
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* Missing LoRAs summary section */
|
||||
/* Improved Missing LoRAs summary section */
|
||||
.missing-loras-summary {
|
||||
margin-bottom: var(--space-3);
|
||||
padding: var(--space-2);
|
||||
background: var(--bg-color);
|
||||
border-radius: var(--border-radius-sm);
|
||||
border: 1px solid var(--lora-error);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.missing-loras-summary h3 {
|
||||
margin-top: 0;
|
||||
margin-bottom: var(--space-2);
|
||||
.summary-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.summary-header h3 {
|
||||
margin: 0;
|
||||
font-size: 1.1em;
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.total-size-info {
|
||||
margin-bottom: var(--space-2);
|
||||
.lora-count-badge {
|
||||
font-size: 0.9em;
|
||||
font-weight: normal;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.total-size-badge {
|
||||
font-size: 0.85em;
|
||||
font-weight: normal;
|
||||
background: var(--lora-surface);
|
||||
padding: 2px 8px;
|
||||
border-radius: var(--border-radius-xs);
|
||||
margin-left: var(--space-1);
|
||||
}
|
||||
|
||||
.toggle-list-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--text-color);
|
||||
padding: 4px 8px;
|
||||
border-radius: var(--border-radius-xs);
|
||||
}
|
||||
|
||||
.toggle-list-btn:hover {
|
||||
background: var(--lora-surface);
|
||||
}
|
||||
|
||||
.missing-loras-list {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
transition: max-height 0.3s ease, margin-top 0.3s ease, padding-top 0.3s ease;
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.missing-loras-list.collapsed {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.missing-loras-list:not(.collapsed) {
|
||||
margin-top: var(--space-1);
|
||||
padding-top: var(--space-1);
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.missing-lora-item {
|
||||
@@ -429,13 +480,45 @@
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.missing-lora-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.missing-lora-name {
|
||||
font-weight: 500;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.lora-base-model {
|
||||
font-size: 0.85em;
|
||||
color: var(--lora-accent);
|
||||
background: oklch(var(--lora-accent) / 0.1);
|
||||
padding: 2px 6px;
|
||||
border-radius: var(--border-radius-xs);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.missing-lora-size {
|
||||
font-size: 0.9em;
|
||||
color: var(--text-color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* Recipe name input select-all behavior */
|
||||
#recipeName:focus {
|
||||
outline: 2px solid var(--lora-accent);
|
||||
}
|
||||
|
||||
/* Prevent layout shift with scrollbar */
|
||||
.modal-content {
|
||||
overflow-y: scroll; /* Always show scrollbar */
|
||||
scrollbar-gutter: stable; /* Reserve space for scrollbar */
|
||||
}
|
||||
|
||||
/* For browsers that don't support scrollbar-gutter */
|
||||
@supports not (scrollbar-gutter: stable) {
|
||||
.modal-content {
|
||||
padding-right: calc(var(--space-2) + var(--scrollbar-width)); /* Add extra padding for scrollbar */
|
||||
}
|
||||
}
|
||||
@@ -186,6 +186,11 @@ export class ImportManager {
|
||||
throw new Error('No LoRA information found in this image');
|
||||
}
|
||||
|
||||
// Store generation parameters if available
|
||||
if (this.recipeData.gen_params) {
|
||||
console.log('Generation parameters found:', this.recipeData.gen_params);
|
||||
}
|
||||
|
||||
// Find missing LoRAs
|
||||
this.missingLoras = this.recipeData.loras.filter(lora => !lora.existsLocally);
|
||||
|
||||
@@ -202,9 +207,24 @@ export class ImportManager {
|
||||
showRecipeDetailsStep() {
|
||||
this.showStep('detailsStep');
|
||||
|
||||
// Set default recipe name from image filename
|
||||
// Set default recipe name from prompt or image filename
|
||||
const recipeName = document.getElementById('recipeName');
|
||||
if (this.recipeImage && !recipeName.value) {
|
||||
if (this.recipeData && this.recipeData.gen_params && this.recipeData.gen_params.prompt) {
|
||||
// Use the first 15 words from the prompt as the default recipe name
|
||||
const promptWords = this.recipeData.gen_params.prompt.split(' ');
|
||||
const truncatedPrompt = promptWords.slice(0, 15).join(' ');
|
||||
recipeName.value = truncatedPrompt;
|
||||
this.recipeName = truncatedPrompt;
|
||||
|
||||
// Set up click handler to select all text for easy editing
|
||||
if (!recipeName.hasSelectAllHandler) {
|
||||
recipeName.addEventListener('click', function() {
|
||||
this.select();
|
||||
});
|
||||
recipeName.hasSelectAllHandler = true;
|
||||
}
|
||||
} else if (this.recipeImage && !recipeName.value) {
|
||||
// Fallback to image filename if no prompt is available
|
||||
const fileName = this.recipeImage.name.split('.')[0];
|
||||
recipeName.value = fileName;
|
||||
this.recipeName = fileName;
|
||||
@@ -386,17 +406,40 @@ export class ImportManager {
|
||||
totalSizeDisplay.textContent = this.formatFileSize(totalSize);
|
||||
}
|
||||
|
||||
// Update header to include count of missing LoRAs
|
||||
const missingLorasHeader = document.querySelector('.summary-header h3');
|
||||
if (missingLorasHeader) {
|
||||
missingLorasHeader.innerHTML = `Missing LoRAs <span class="lora-count-badge">(${this.missingLoras.length})</span> <span id="totalDownloadSize" class="total-size-badge">${this.formatFileSize(totalSize)}</span>`;
|
||||
}
|
||||
|
||||
// Generate missing LoRAs list
|
||||
missingLorasList.innerHTML = this.missingLoras.map(lora => {
|
||||
const sizeDisplay = lora.size ? this.formatFileSize(lora.size) : 'Unknown size';
|
||||
const baseModel = lora.baseModel ? `<span class="lora-base-model">${lora.baseModel}</span>` : '';
|
||||
|
||||
return `
|
||||
<div class="missing-lora-item">
|
||||
<div class="missing-lora-name">${lora.name}</div>
|
||||
<div class="missing-lora-info">
|
||||
<div class="missing-lora-name">${lora.name}</div>
|
||||
${baseModel}
|
||||
</div>
|
||||
<div class="missing-lora-size">${sizeDisplay}</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
// Set up toggle for missing LoRAs list
|
||||
const toggleBtn = document.getElementById('toggleMissingLorasList');
|
||||
if (toggleBtn) {
|
||||
toggleBtn.addEventListener('click', () => {
|
||||
missingLorasList.classList.toggle('collapsed');
|
||||
const icon = toggleBtn.querySelector('i');
|
||||
if (icon) {
|
||||
icon.classList.toggle('fa-chevron-down');
|
||||
icon.classList.toggle('fa-chevron-up');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch LoRA roots
|
||||
@@ -470,7 +513,16 @@ export class ImportManager {
|
||||
formData.append('image', this.recipeImage);
|
||||
formData.append('name', this.recipeName);
|
||||
formData.append('tags', JSON.stringify(this.recipeTags));
|
||||
formData.append('metadata', JSON.stringify(this.recipeData));
|
||||
|
||||
// Prepare complete metadata including generation parameters
|
||||
const completeMetadata = {
|
||||
base_model: this.recipeData.base_model || "",
|
||||
loras: this.recipeData.loras || [],
|
||||
gen_params: this.recipeData.gen_params || {},
|
||||
raw_metadata: this.recipeData.raw_metadata || {}
|
||||
};
|
||||
|
||||
formData.append('metadata', JSON.stringify(completeMetadata));
|
||||
|
||||
// Send save request
|
||||
const response = await fetch('/api/recipes/save', {
|
||||
@@ -481,8 +533,7 @@ export class ImportManager {
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
// Handle successful save
|
||||
// Show success message for recipe save
|
||||
showToast(`Recipe "${this.recipeName}" saved successfully`, 'success');
|
||||
|
||||
|
||||
// Check if we need to download LoRAs
|
||||
if (this.missingLoras.length > 0) {
|
||||
@@ -602,6 +653,9 @@ export class ImportManager {
|
||||
showToast(`Downloaded ${completedDownloads} of ${this.missingLoras.length} LoRAs`, 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
// Show success message for recipe save
|
||||
showToast(`Recipe "${this.recipeName}" saved successfully`, 'success');
|
||||
|
||||
// Close modal and reload recipes
|
||||
modalManager.closeModal('importModal');
|
||||
|
||||
Reference in New Issue
Block a user