feat: add auto download setting for example images with UI toggle and functionality, fixes #288

This commit is contained in:
Will Miao
2025-08-05 16:49:46 +08:00
parent 83be5cfa64
commit 3b96bfe5af
3 changed files with 179 additions and 0 deletions

View File

@@ -1,4 +1,5 @@
import { showToast } from '../utils/uiHelpers.js';
import { state } from '../state/index.js';
import { getStorageItem, setStorageItem } from '../utils/storageHelpers.js';
// ExampleImagesManager.js
@@ -14,6 +15,12 @@ class ExampleImagesManager {
this.isMigrating = false; // Track migration state separately from downloading
this.hasShownCompletionToast = false; // Flag to track if completion toast has been shown
// Auto download properties
this.autoDownloadInterval = null;
this.lastAutoDownloadCheck = 0;
this.autoDownloadCheckInterval = 10 * 60 * 1000; // 10 minutes in milliseconds
this.pageInitTime = Date.now(); // Track when page was initialized
// Initialize download path field and check download status
this.initializePathOptions();
this.checkDownloadStatus();
@@ -48,6 +55,14 @@ class ExampleImagesManager {
if (collapseBtn) {
collapseBtn.onclick = () => this.toggleProgressPanel();
}
// Setup auto download if enabled
if (state.global.settings.autoDownloadExampleImages) {
this.setupAutoDownload();
}
// Make this instance globally accessible
window.exampleImagesManager = this;
}
// Initialize event listeners for buttons
@@ -133,6 +148,15 @@ class ExampleImagesManager {
console.error('Failed to update example images path:', error);
}
}
// Setup or clear auto download based on path availability
if (state.global.settings.autoDownloadExampleImages) {
if (hasPath) {
this.setupAutoDownload();
} else {
this.clearAutoDownload();
}
}
});
} catch (error) {
console.error('Failed to initialize path options:', error);
@@ -646,6 +670,121 @@ class ExampleImagesManager {
}
}
}
setupAutoDownload() {
// Only setup if conditions are met
if (!this.canAutoDownload()) {
return;
}
// Clear any existing interval
this.clearAutoDownload();
// Wait at least 30 seconds after page initialization before first check
const timeSinceInit = Date.now() - this.pageInitTime;
const initialDelay = Math.max(60000 - timeSinceInit, 5000); // At least 5 seconds, up to 60 seconds
console.log(`Setting up auto download with initial delay of ${initialDelay}ms`);
setTimeout(() => {
// Do initial check
this.performAutoDownloadCheck();
// Set up recurring interval
this.autoDownloadInterval = setInterval(() => {
this.performAutoDownloadCheck();
}, this.autoDownloadCheckInterval);
}, initialDelay);
}
clearAutoDownload() {
if (this.autoDownloadInterval) {
clearInterval(this.autoDownloadInterval);
this.autoDownloadInterval = null;
console.log('Auto download interval cleared');
}
}
canAutoDownload() {
// Check if auto download is enabled
if (!state.global.settings.autoDownloadExampleImages) {
return false;
}
// Check if download path is set
const pathInput = document.getElementById('exampleImagesPath');
if (!pathInput || !pathInput.value.trim()) {
return false;
}
// Check if already downloading
if (this.isDownloading) {
return false;
}
return true;
}
async performAutoDownloadCheck() {
const now = Date.now();
// Prevent too frequent checks (minimum 2 minutes between checks)
if (now - this.lastAutoDownloadCheck < 2 * 60 * 1000) {
console.log('Skipping auto download check - too soon since last check');
return;
}
this.lastAutoDownloadCheck = now;
if (!this.canAutoDownload()) {
console.log('Auto download conditions not met, skipping check');
return;
}
try {
console.log('Performing auto download check...');
const outputDir = document.getElementById('exampleImagesPath').value;
const optimize = document.getElementById('optimizeExampleImages').checked;
const response = await fetch('/api/download-example-images', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
output_dir: outputDir,
optimize: optimize,
model_types: ['lora', 'checkpoint', 'embedding'],
auto_mode: true // Flag to indicate this is an automatic download
})
});
const data = await response.json();
if (data.success) {
// Only show progress if there are actually items to download
if (data.status && data.status.total > 0) {
this.isDownloading = true;
this.isPaused = false;
this.hasShownCompletionToast = false;
this.startTime = new Date();
this.updateUI(data.status);
this.showProgressPanel();
this.startProgressUpdates();
this.updateDownloadButtonText();
console.log(`Auto download started: ${data.status.total} items to process`);
} else {
console.log('Auto download check completed - no new items to download');
}
} else {
console.warn('Auto download check failed:', data.error);
}
} catch (error) {
console.error('Auto download check error:', error);
}
}
}
// Create singleton instance

View File

@@ -48,6 +48,11 @@ export class SettingsManager {
state.global.settings.optimizeExampleImages = true;
}
// Set default for autoDownloadExampleImages if undefined
if (state.global.settings.autoDownloadExampleImages === undefined) {
state.global.settings.autoDownloadExampleImages = true;
}
// Set default for cardInfoDisplay if undefined
if (state.global.settings.cardInfoDisplay === undefined) {
state.global.settings.cardInfoDisplay = 'always';
@@ -195,6 +200,12 @@ export class SettingsManager {
optimizeExampleImagesCheckbox.checked = state.global.settings.optimizeExampleImages || false;
}
// Set auto download example images setting
const autoDownloadExampleImagesCheckbox = document.getElementById('autoDownloadExampleImages');
if (autoDownloadExampleImagesCheckbox) {
autoDownloadExampleImagesCheckbox.checked = state.global.settings.autoDownloadExampleImages || false;
}
// Set download path template setting
const downloadPathTemplateSelect = document.getElementById('downloadPathTemplate');
if (downloadPathTemplateSelect) {
@@ -547,6 +558,8 @@ export class SettingsManager {
state.global.settings.autoplayOnHover = value;
} else if (settingKey === 'optimize_example_images') {
state.global.settings.optimizeExampleImages = value;
} else if (settingKey === 'auto_download_example_images') {
state.global.settings.autoDownloadExampleImages = value;
} else if (settingKey === 'compact_mode') {
state.global.settings.compactMode = value;
} else {
@@ -581,6 +594,15 @@ export class SettingsManager {
// Apply frontend settings immediately
this.applyFrontendSettings();
// Trigger auto download setup/teardown when setting changes
if (settingKey === 'auto_download_example_images' && window.exampleImagesManager) {
if (value) {
window.exampleImagesManager.setupAutoDownload();
} else {
window.exampleImagesManager.clearAutoDownload();
}
}
if (settingKey === 'show_only_sfw') {
this.reloadContent();
}

View File

@@ -272,6 +272,24 @@
</div>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">
<label for="autoDownloadExampleImages">Auto Download Example Images</label>
</div>
<div class="setting-control">
<label class="toggle-switch">
<input type="checkbox" id="autoDownloadExampleImages" checked
onchange="settingsManager.saveToggleSetting('autoDownloadExampleImages', 'auto_download_example_images')">
<span class="toggle-slider"></span>
</label>
</div>
</div>
<div class="input-help">
Automatically download example images for models that don't have them (requires download location to be set)
</div>
</div>
<div class="setting-item">
<div class="setting-row">
<div class="setting-info">