mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
Refactor example images management by removing centralized examples settings and migration functionality
This commit is contained in:
@@ -306,18 +306,6 @@ body.modal-open {
|
|||||||
width: 100%; /* Full width */
|
width: 100%; /* Full width */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Migrate control styling */
|
|
||||||
.migrate-control {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.migrate-control input {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 统一各个 section 的样式 */
|
/* 统一各个 section 的样式 */
|
||||||
.support-section,
|
.support-section,
|
||||||
.changelog-section,
|
.changelog-section,
|
||||||
@@ -375,12 +363,6 @@ body.modal-open {
|
|||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(255, 255, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add disabled style for setting items */
|
|
||||||
.setting-item[data-requires-centralized="true"].disabled {
|
|
||||||
opacity: 0.6;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Control row with label and input together */
|
/* Control row with label and input together */
|
||||||
.setting-row {
|
.setting-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -169,14 +169,9 @@ async function loadExampleImages(images, modelHash, filePath) {
|
|||||||
// First fetch local example files
|
// First fetch local example files
|
||||||
let localFiles = [];
|
let localFiles = [];
|
||||||
try {
|
try {
|
||||||
// Choose endpoint based on centralized examples setting
|
const endpoint = '/api/example-image-files';
|
||||||
const useCentralized = state.global.settings.useCentralizedExamples !== false;
|
|
||||||
const endpoint = useCentralized ? '/api/example-image-files' : '/api/model-example-files';
|
|
||||||
|
|
||||||
// Use different params based on endpoint
|
const params = `model_hash=${modelHash}`;
|
||||||
const params = useCentralized ?
|
|
||||||
`model_hash=${modelHash}` :
|
|
||||||
`file_path=${encodeURIComponent(filePath)}`;
|
|
||||||
|
|
||||||
const response = await fetch(`${endpoint}?${params}`);
|
const response = await fetch(`${endpoint}?${params}`);
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
|
|||||||
@@ -48,12 +48,6 @@ class ExampleImagesManager {
|
|||||||
if (collapseBtn) {
|
if (collapseBtn) {
|
||||||
collapseBtn.onclick = () => this.toggleProgressPanel();
|
collapseBtn.onclick = () => this.toggleProgressPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize migration button handler
|
|
||||||
const migrateBtn = document.getElementById('exampleImagesMigrateBtn');
|
|
||||||
if (migrateBtn) {
|
|
||||||
migrateBtn.onclick = () => this.handleMigrateButton();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize event listeners for buttons
|
// Initialize event listeners for buttons
|
||||||
@@ -149,95 +143,6 @@ class ExampleImagesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method to handle migrate button click
|
|
||||||
async handleMigrateButton() {
|
|
||||||
if (this.isDownloading || this.isMigrating) {
|
|
||||||
if (this.isPaused) {
|
|
||||||
// If paused, resume
|
|
||||||
this.resumeDownload();
|
|
||||||
} else {
|
|
||||||
showToast('Migration or download already in progress', 'info');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start migration
|
|
||||||
this.startMigrate();
|
|
||||||
}
|
|
||||||
|
|
||||||
async startMigrate() {
|
|
||||||
try {
|
|
||||||
const outputDir = document.getElementById('exampleImagesPath').value || '';
|
|
||||||
|
|
||||||
if (!outputDir) {
|
|
||||||
showToast('Please enter a download location first', 'warning');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update path in backend settings before starting migration
|
|
||||||
try {
|
|
||||||
const pathUpdateResponse = await fetch('/api/settings', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
example_images_path: outputDir
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!pathUpdateResponse.ok) {
|
|
||||||
throw new Error(`HTTP error! Status: ${pathUpdateResponse.status}`);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to update example images path:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const pattern = document.getElementById('exampleImagesMigratePattern').value || '{model}.example.{index}.{ext}';
|
|
||||||
const optimize = document.getElementById('optimizeExampleImages').checked;
|
|
||||||
|
|
||||||
const response = await fetch('/api/migrate-example-images', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
output_dir: outputDir,
|
|
||||||
pattern: pattern,
|
|
||||||
optimize: optimize,
|
|
||||||
model_types: ['lora', 'checkpoint']
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (data.success) {
|
|
||||||
this.isDownloading = true;
|
|
||||||
this.isMigrating = true;
|
|
||||||
this.isPaused = false;
|
|
||||||
this.hasShownCompletionToast = false; // Reset toast flag when starting new migration
|
|
||||||
this.startTime = new Date();
|
|
||||||
this.updateUI(data.status);
|
|
||||||
this.showProgressPanel();
|
|
||||||
this.startProgressUpdates();
|
|
||||||
// Update button text
|
|
||||||
const btnTextElement = document.getElementById('exampleDownloadBtnText');
|
|
||||||
if (btnTextElement) {
|
|
||||||
btnTextElement.textContent = "Resume";
|
|
||||||
}
|
|
||||||
showToast('Example images migration started', 'success');
|
|
||||||
|
|
||||||
// Close settings modal
|
|
||||||
modalManager.closeModal('settingsModal');
|
|
||||||
} else {
|
|
||||||
showToast(data.error || 'Failed to start migration', 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to start migration:', error);
|
|
||||||
showToast('Failed to start migration', 'error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkDownloadStatus() {
|
async checkDownloadStatus() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/example-images-status');
|
const response = await fetch('/api/example-images-status');
|
||||||
|
|||||||
@@ -36,11 +36,6 @@ export class SettingsManager {
|
|||||||
if (state.global.settings.optimizeExampleImages === undefined) {
|
if (state.global.settings.optimizeExampleImages === undefined) {
|
||||||
state.global.settings.optimizeExampleImages = true;
|
state.global.settings.optimizeExampleImages = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set default for useCentralizedExamples if undefined
|
|
||||||
if (state.global.settings.useCentralizedExamples === undefined) {
|
|
||||||
state.global.settings.useCentralizedExamples = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert old boolean compactMode to new displayDensity string
|
// Convert old boolean compactMode to new displayDensity string
|
||||||
if (typeof state.global.settings.displayDensity === 'undefined') {
|
if (typeof state.global.settings.displayDensity === 'undefined') {
|
||||||
@@ -114,14 +109,6 @@ export class SettingsManager {
|
|||||||
optimizeExampleImagesCheckbox.checked = state.global.settings.optimizeExampleImages || false;
|
optimizeExampleImagesCheckbox.checked = state.global.settings.optimizeExampleImages || false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set centralized examples setting
|
|
||||||
const useCentralizedExamplesCheckbox = document.getElementById('useCentralizedExamples');
|
|
||||||
if (useCentralizedExamplesCheckbox) {
|
|
||||||
useCentralizedExamplesCheckbox.checked = state.global.settings.useCentralizedExamples !== false;
|
|
||||||
// Update dependent controls
|
|
||||||
this.updateExamplesControlsState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load default lora root
|
// Load default lora root
|
||||||
await this.loadLoraRoots();
|
await this.loadLoraRoots();
|
||||||
|
|
||||||
@@ -196,10 +183,6 @@ export class SettingsManager {
|
|||||||
state.global.settings.optimizeExampleImages = value;
|
state.global.settings.optimizeExampleImages = value;
|
||||||
} else if (settingKey === 'compact_mode') {
|
} else if (settingKey === 'compact_mode') {
|
||||||
state.global.settings.compactMode = value;
|
state.global.settings.compactMode = value;
|
||||||
} else if (settingKey === 'use_centralized_examples') {
|
|
||||||
state.global.settings.useCentralizedExamples = value;
|
|
||||||
// Update dependent controls state
|
|
||||||
this.updateExamplesControlsState();
|
|
||||||
} else {
|
} else {
|
||||||
// For any other settings that might be added in the future
|
// For any other settings that might be added in the future
|
||||||
state.global.settings[settingKey] = value;
|
state.global.settings[settingKey] = value;
|
||||||
@@ -523,42 +506,6 @@ export class SettingsManager {
|
|||||||
// Add the appropriate density class
|
// Add the appropriate density class
|
||||||
grid.classList.add(`${density}-density`);
|
grid.classList.add(`${density}-density`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply centralized examples toggle state
|
|
||||||
this.updateExamplesControlsState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new method to update example control states
|
|
||||||
updateExamplesControlsState() {
|
|
||||||
const useCentralized = state.global.settings.useCentralizedExamples !== false;
|
|
||||||
|
|
||||||
// Find all controls that require centralized mode
|
|
||||||
const exampleSections = document.querySelectorAll('[data-requires-centralized="true"]');
|
|
||||||
exampleSections.forEach(section => {
|
|
||||||
// Enable/disable all inputs and buttons in the section
|
|
||||||
const controls = section.querySelectorAll('input, button, select');
|
|
||||||
controls.forEach(control => {
|
|
||||||
control.disabled = !useCentralized;
|
|
||||||
|
|
||||||
// Add/remove disabled class for styling
|
|
||||||
if (control.classList.contains('primary-btn') || control.classList.contains('secondary-btn')) {
|
|
||||||
if (!useCentralized) {
|
|
||||||
control.classList.add('disabled');
|
|
||||||
} else {
|
|
||||||
control.classList.remove('disabled');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Visually show the section as disabled
|
|
||||||
if (!useCentralized) {
|
|
||||||
section.style.opacity = '0.6';
|
|
||||||
section.style.pointerEvents = 'none';
|
|
||||||
} else {
|
|
||||||
section.style.opacity = '';
|
|
||||||
section.style.pointerEvents = '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -256,26 +256,6 @@
|
|||||||
<h3>Example Images</h3>
|
<h3>Example Images</h3>
|
||||||
|
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<div class="setting-row">
|
|
||||||
<div class="setting-info">
|
|
||||||
<label for="useCentralizedExamples">Use Centralized Example Storage</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-control">
|
|
||||||
<label class="toggle-switch">
|
|
||||||
<input type="checkbox" id="useCentralizedExamples" checked
|
|
||||||
onchange="settingsManager.saveToggleSetting('useCentralizedExamples', 'use_centralized_examples')">
|
|
||||||
<span class="toggle-slider"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="input-help">
|
|
||||||
When enabled (recommended), example images are stored in a central folder for better organization and performance.
|
|
||||||
When disabled, only example images stored alongside models (e.g., model-name.example.0.jpg) will be shown, but download
|
|
||||||
and management features will be unavailable.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item" data-requires-centralized="true">
|
|
||||||
<div class="setting-row">
|
<div class="setting-row">
|
||||||
<div class="setting-info">
|
<div class="setting-info">
|
||||||
<label for="exampleImagesPath">Download Location <i class="fas fa-sync-alt restart-required-icon" title="Requires restart"></i></label>
|
<label for="exampleImagesPath">Download Location <i class="fas fa-sync-alt restart-required-icon" title="Requires restart"></i></label>
|
||||||
@@ -291,29 +271,8 @@
|
|||||||
Enter the folder path where example images from Civitai will be saved
|
Enter the folder path where example images from Civitai will be saved
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- New migrate section -->
|
|
||||||
<div class="setting-item" data-requires-centralized="true">
|
|
||||||
<div class="setting-row">
|
|
||||||
<div class="setting-info">
|
|
||||||
<label for="exampleImagesMigratePattern">Migrate Existing Example Images</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-control migrate-control">
|
|
||||||
<input type="text" id="exampleImagesMigratePattern"
|
|
||||||
placeholder="{model}.example.{index}.{ext}"
|
|
||||||
value="{model}.example.{index}.{ext}" />
|
|
||||||
<button id="exampleImagesMigrateBtn" class="secondary-btn">
|
|
||||||
<i class="fas fa-file-import"></i> <span>Migrate</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="input-help">
|
|
||||||
Pattern to find existing example images. Use {model} for model filename, {index} for numbering, and {ext} for file extension.<br>
|
|
||||||
Example patterns: "{model}.example.{index}.{ext}", "{model}_{index}.{ext}", "{model}/{model}.example.{index}.{ext}"
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="setting-item" data-requires-centralized="true">
|
<div class="setting-item">
|
||||||
<div class="setting-row">
|
<div class="setting-row">
|
||||||
<div class="setting-info">
|
<div class="setting-info">
|
||||||
<label for="optimizeExampleImages">Optimize Downloaded Images</label>
|
<label for="optimizeExampleImages">Optimize Downloaded Images</label>
|
||||||
|
|||||||
Reference in New Issue
Block a user