Refactor example images management by removing centralized examples settings and migration functionality

This commit is contained in:
Will Miao
2025-06-16 18:29:37 +08:00
parent cb0a8e0413
commit 1ccaf33aac
5 changed files with 3 additions and 215 deletions

View File

@@ -306,18 +306,6 @@ body.modal-open {
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 的样式 */
.support-section,
.changelog-section,
@@ -375,12 +363,6 @@ body.modal-open {
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 */
.setting-row {
display: flex;

View File

@@ -169,14 +169,9 @@ async function loadExampleImages(images, modelHash, filePath) {
// First fetch local example files
let localFiles = [];
try {
// Choose endpoint based on centralized examples setting
const useCentralized = state.global.settings.useCentralizedExamples !== false;
const endpoint = useCentralized ? '/api/example-image-files' : '/api/model-example-files';
const endpoint = '/api/example-image-files';
// Use different params based on endpoint
const params = useCentralized ?
`model_hash=${modelHash}` :
`file_path=${encodeURIComponent(filePath)}`;
const params = `model_hash=${modelHash}`;
const response = await fetch(`${endpoint}?${params}`);
const result = await response.json();

View File

@@ -48,12 +48,6 @@ class ExampleImagesManager {
if (collapseBtn) {
collapseBtn.onclick = () => this.toggleProgressPanel();
}
// Initialize migration button handler
const migrateBtn = document.getElementById('exampleImagesMigrateBtn');
if (migrateBtn) {
migrateBtn.onclick = () => this.handleMigrateButton();
}
}
// 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() {
try {
const response = await fetch('/api/example-images-status');

View File

@@ -36,11 +36,6 @@ export class SettingsManager {
if (state.global.settings.optimizeExampleImages === undefined) {
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
if (typeof state.global.settings.displayDensity === 'undefined') {
@@ -114,14 +109,6 @@ export class SettingsManager {
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
await this.loadLoraRoots();
@@ -196,10 +183,6 @@ export class SettingsManager {
state.global.settings.optimizeExampleImages = value;
} else if (settingKey === 'compact_mode') {
state.global.settings.compactMode = value;
} else if (settingKey === 'use_centralized_examples') {
state.global.settings.useCentralizedExamples = value;
// Update dependent controls state
this.updateExamplesControlsState();
} else {
// For any other settings that might be added in the future
state.global.settings[settingKey] = value;
@@ -523,42 +506,6 @@ export class SettingsManager {
// Add the appropriate density class
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 = '';
}
});
}
}

View File

@@ -256,26 +256,6 @@
<h3>Example Images</h3>
<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-info">
<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
</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-info">
<label for="optimizeExampleImages">Optimize Downloaded Images</label>