mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-24 14:42:11 -03:00
refactor: streamline example images download functionality and UI updates
This commit is contained in:
@@ -48,9 +48,6 @@ class MiscRoutes:
|
|||||||
app.router.add_post('/api/pause-example-images', MiscRoutes.pause_example_images)
|
app.router.add_post('/api/pause-example-images', MiscRoutes.pause_example_images)
|
||||||
app.router.add_post('/api/resume-example-images', MiscRoutes.resume_example_images)
|
app.router.add_post('/api/resume-example-images', MiscRoutes.resume_example_images)
|
||||||
|
|
||||||
# Folder browser route
|
|
||||||
app.router.add_post('/api/browse-folder', MiscRoutes.browse_folder)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def update_settings(request):
|
async def update_settings(request):
|
||||||
"""Update application settings"""
|
"""Update application settings"""
|
||||||
@@ -67,17 +64,10 @@ class MiscRoutes:
|
|||||||
'error': f"Path does not exist: {value}"
|
'error': f"Path does not exist: {value}"
|
||||||
})
|
})
|
||||||
|
|
||||||
# Add static route for example images path if it changed
|
# Path changed - server restart required for new path to take effect
|
||||||
old_path = settings.get('example_images_path')
|
old_path = settings.get('example_images_path')
|
||||||
if old_path != value:
|
if old_path != value:
|
||||||
# We need to add the new static route
|
logger.info(f"Example images path changed to {value} - server restart required")
|
||||||
# Note: we can't remove old routes in aiohttp, but we can create a new one
|
|
||||||
app = request.app
|
|
||||||
try:
|
|
||||||
app.router.add_static('/example_images_static', value)
|
|
||||||
logger.info(f"Added static route for example images: /example_images_static -> {value}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"Could not add static route for example images: {str(e)}")
|
|
||||||
|
|
||||||
# Save to settings
|
# Save to settings
|
||||||
settings.set(key, value)
|
settings.set(key, value)
|
||||||
@@ -174,7 +164,7 @@ class MiscRoutes:
|
|||||||
output_dir = data.get('output_dir')
|
output_dir = data.get('output_dir')
|
||||||
optimize = data.get('optimize', True)
|
optimize = data.get('optimize', True)
|
||||||
model_types = data.get('model_types', ['lora', 'checkpoint'])
|
model_types = data.get('model_types', ['lora', 'checkpoint'])
|
||||||
delay = float(data.get('delay', 1.0))
|
delay = float(data.get('delay', 0.2))
|
||||||
|
|
||||||
if not output_dir:
|
if not output_dir:
|
||||||
return web.json_response({
|
return web.json_response({
|
||||||
@@ -494,55 +484,3 @@ class MiscRoutes:
|
|||||||
|
|
||||||
# Set download status to not downloading
|
# Set download status to not downloading
|
||||||
is_downloading = False
|
is_downloading = False
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
async def browse_folder(request):
|
|
||||||
"""Open a folder browser dialog and return the selected path
|
|
||||||
|
|
||||||
Expects a JSON body with:
|
|
||||||
{
|
|
||||||
"initial_dir": "string" // Optional initial directory
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# Parse the request body
|
|
||||||
data = await request.json()
|
|
||||||
initial_dir = data.get('initial_dir', '')
|
|
||||||
|
|
||||||
# If initial_dir doesn't exist, use a default path
|
|
||||||
if initial_dir and not os.path.isdir(initial_dir):
|
|
||||||
initial_dir = ''
|
|
||||||
|
|
||||||
# Create a hidden root window for the dialog
|
|
||||||
root = tk.Tk()
|
|
||||||
root.withdraw() # Hide the root window
|
|
||||||
|
|
||||||
# Show the folder selection dialog
|
|
||||||
folder_path = filedialog.askdirectory(
|
|
||||||
initialdir=initial_dir,
|
|
||||||
title="Select folder for example images"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Destroy the root window
|
|
||||||
root.destroy()
|
|
||||||
|
|
||||||
if folder_path:
|
|
||||||
# Convert to proper path format for the OS
|
|
||||||
folder_path = os.path.normpath(folder_path)
|
|
||||||
|
|
||||||
return web.json_response({
|
|
||||||
'success': True,
|
|
||||||
'folder': folder_path
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
return web.json_response({
|
|
||||||
'success': False,
|
|
||||||
'error': 'No folder selected'
|
|
||||||
})
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to browse folder: {e}", exc_info=True)
|
|
||||||
return web.json_response({
|
|
||||||
'success': False,
|
|
||||||
'error': str(e)
|
|
||||||
}, status=500)
|
|
||||||
|
|||||||
@@ -190,14 +190,6 @@
|
|||||||
border-color: var(--lora-border);
|
border-color: var(--lora-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add disabled button styles */
|
|
||||||
.primary-btn.disabled {
|
|
||||||
background-color: var(--border-color);
|
|
||||||
color: var(--text-color);
|
|
||||||
opacity: 0.7;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enhance the local badge to make it more noticeable */
|
/* Enhance the local badge to make it more noticeable */
|
||||||
.version-item.exists-locally {
|
.version-item.exists-locally {
|
||||||
background: oklch(var(--lora-accent) / 0.05);
|
background: oklch(var(--lora-accent) / 0.05);
|
||||||
|
|||||||
@@ -502,7 +502,7 @@ input:checked + .toggle-slider:before {
|
|||||||
gap: var(--space-2);
|
gap: var(--space-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.download-buttons .primary-btn {
|
.primary-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
@@ -516,30 +516,80 @@ input:checked + .toggle-slider:before {
|
|||||||
font-size: 0.95em;
|
font-size: 0.95em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.download-buttons .primary-btn:hover {
|
.primary-btn:hover {
|
||||||
background-color: oklch(var(--lora-accent) / 0.9);
|
background-color: oklch(from var(--lora-accent) l c h / 85%);
|
||||||
|
color: var(--lora-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.path-browser-control {
|
/* Secondary button styles */
|
||||||
|
.secondary-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
background-color: var(--card-bg);
|
||||||
|
color: var(--text-color);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary-btn:hover {
|
||||||
|
background-color: var(--border-color);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disabled button styles */
|
||||||
|
.primary-btn.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
background-color: var(--lora-accent);
|
||||||
|
color: var(--lora-text);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary-btn.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark theme specific button adjustments */
|
||||||
|
[data-theme="dark"] .primary-btn:hover {
|
||||||
|
background-color: oklch(from var(--lora-accent) l c h / 75%);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .secondary-btn {
|
||||||
|
background-color: var(--lora-surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .secondary-btn:hover {
|
||||||
|
background-color: oklch(35% 0.02 256 / 0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-btn.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.path-control {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.path-browser-control input[type="text"] {
|
.path-control input[type="text"] {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
padding: 6px 10px;
|
||||||
|
border-radius: var(--border-radius-xs);
|
||||||
.browse-btn {
|
|
||||||
white-space: nowrap;
|
|
||||||
padding: 6px 12px;
|
|
||||||
background-color: var(--button-bg);
|
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 4px;
|
background-color: var(--lora-surface);
|
||||||
cursor: pointer;
|
color: var(--text-color);
|
||||||
}
|
font-size: 0.95em;
|
||||||
|
height: 32px;
|
||||||
.browse-btn:hover {
|
|
||||||
background-color: var(--button-hover-bg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary-btn.disabled {
|
.primary-btn.disabled {
|
||||||
|
|||||||
@@ -88,7 +88,8 @@
|
|||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-container {
|
/* Use specific selectors to avoid conflicts with loading.css */
|
||||||
|
.progress-panel .progress-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: var(--lora-border);
|
background-color: var(--lora-border);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@@ -96,7 +97,7 @@
|
|||||||
height: var(--space-1);
|
height: var(--space-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar {
|
.progress-panel .progress-bar {
|
||||||
width: 0%;
|
width: 0%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: var(--lora-accent);
|
background-color: var(--lora-accent);
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ class ExampleImagesManager {
|
|||||||
this.isPaused = false;
|
this.isPaused = false;
|
||||||
this.progressUpdateInterval = null;
|
this.progressUpdateInterval = null;
|
||||||
this.startTime = null;
|
this.startTime = null;
|
||||||
this.progressPanel = document.getElementById('exampleImagesProgress');
|
this.progressPanel = null;
|
||||||
|
|
||||||
// Wait for DOM before initializing event listeners
|
// Wait for DOM before initializing event listeners
|
||||||
document.addEventListener('DOMContentLoaded', () => this.initEventListeners());
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
this.initEventListeners();
|
||||||
|
// Initialize progress panel reference
|
||||||
|
this.progressPanel = document.getElementById('exampleImagesProgress');
|
||||||
|
});
|
||||||
|
|
||||||
// Initialize download path field
|
// Initialize download path field
|
||||||
this.initializePathOptions();
|
this.initializePathOptions();
|
||||||
@@ -22,14 +26,9 @@ class ExampleImagesManager {
|
|||||||
|
|
||||||
// Initialize event listeners for buttons
|
// Initialize event listeners for buttons
|
||||||
initEventListeners() {
|
initEventListeners() {
|
||||||
const startBtn = document.getElementById('startExampleDownloadBtn');
|
const downloadBtn = document.getElementById('exampleImagesDownloadBtn');
|
||||||
if (startBtn) {
|
if (downloadBtn) {
|
||||||
startBtn.onclick = () => this.startDownload();
|
downloadBtn.onclick = () => this.handleDownloadButton();
|
||||||
}
|
|
||||||
|
|
||||||
const resumeBtn = document.getElementById('resumeExampleDownloadBtn');
|
|
||||||
if (resumeBtn) {
|
|
||||||
resumeBtn.onclick = () => this.resumeDownload();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,12 +48,6 @@ class ExampleImagesManager {
|
|||||||
this.updateDownloadButtonState(false);
|
this.updateDownloadButtonState(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add event listener to the browse button
|
|
||||||
const browseButton = document.getElementById('browseExampleImagesPath');
|
|
||||||
if (browseButton) {
|
|
||||||
browseButton.addEventListener('click', () => this.browseFolderDialog());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add event listener to validate path input
|
// Add event listener to validate path input
|
||||||
pathInput.addEventListener('input', async () => {
|
pathInput.addEventListener('input', async () => {
|
||||||
const hasPath = pathInput.value.trim() !== '';
|
const hasPath = pathInput.value.trim() !== '';
|
||||||
@@ -98,47 +91,29 @@ class ExampleImagesManager {
|
|||||||
|
|
||||||
// Method to update download button state
|
// Method to update download button state
|
||||||
updateDownloadButtonState(enabled) {
|
updateDownloadButtonState(enabled) {
|
||||||
const startBtn = document.getElementById('startExampleDownloadBtn');
|
const downloadBtn = document.getElementById('exampleImagesDownloadBtn');
|
||||||
if (startBtn) {
|
if (downloadBtn) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
startBtn.classList.remove('disabled');
|
downloadBtn.classList.remove('disabled');
|
||||||
startBtn.disabled = false;
|
downloadBtn.disabled = false;
|
||||||
} else {
|
} else {
|
||||||
startBtn.classList.add('disabled');
|
downloadBtn.classList.add('disabled');
|
||||||
startBtn.disabled = true;
|
downloadBtn.disabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method to open folder browser dialog
|
// Method to handle download button click based on current state
|
||||||
async browseFolderDialog() {
|
async handleDownloadButton() {
|
||||||
try {
|
if (this.isDownloading && this.isPaused) {
|
||||||
const response = await fetch('/api/browse-folder', {
|
// If download is paused, resume it
|
||||||
method: 'POST',
|
this.resumeDownload();
|
||||||
headers: {
|
} else if (!this.isDownloading) {
|
||||||
'Content-Type': 'application/json'
|
// If no download in progress, start a new one
|
||||||
},
|
this.startDownload();
|
||||||
body: JSON.stringify({
|
} else {
|
||||||
initial_dir: getStorageItem('example_images_path', '')
|
// If download is in progress, show info toast
|
||||||
})
|
showToast('Download already in progress', 'info');
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (data.success && data.folder) {
|
|
||||||
const pathInput = document.getElementById('exampleImagesPath');
|
|
||||||
pathInput.value = data.folder;
|
|
||||||
setStorageItem('example_images_path', data.folder);
|
|
||||||
this.updateDownloadButtonState(true);
|
|
||||||
showToast('Example images path updated successfully', 'success');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to browse folder:', error);
|
|
||||||
showToast('Failed to browse folder. Please ensure the server supports this feature.', 'error');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,13 +126,27 @@ class ExampleImagesManager {
|
|||||||
this.isDownloading = data.is_downloading;
|
this.isDownloading = data.is_downloading;
|
||||||
this.isPaused = data.status.status === 'paused';
|
this.isPaused = data.status.status === 'paused';
|
||||||
|
|
||||||
if (this.isDownloading) {
|
// Update download button text based on status
|
||||||
this.updateUI(data.status);
|
this.updateDownloadButtonText();
|
||||||
this.showProgressPanel();
|
|
||||||
|
|
||||||
// Start the progress update interval if downloading
|
if (this.isDownloading) {
|
||||||
if (!this.progressUpdateInterval) {
|
// Ensure progress panel exists before updating UI
|
||||||
this.startProgressUpdates();
|
if (!this.progressPanel) {
|
||||||
|
this.progressPanel = document.getElementById('exampleImagesProgress');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.progressPanel) {
|
||||||
|
this.updateUI(data.status);
|
||||||
|
this.showProgressPanel();
|
||||||
|
|
||||||
|
// Start the progress update interval if downloading
|
||||||
|
if (!this.progressUpdateInterval) {
|
||||||
|
this.startProgressUpdates();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn('Progress panel not found, will retry on next update');
|
||||||
|
// Set a shorter timeout to try again
|
||||||
|
setTimeout(() => this.checkDownloadStatus(), 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,6 +155,18 @@ class ExampleImagesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update download button text based on current state
|
||||||
|
updateDownloadButtonText() {
|
||||||
|
const btnTextElement = document.getElementById('exampleDownloadBtnText');
|
||||||
|
if (btnTextElement) {
|
||||||
|
if (this.isDownloading && this.isPaused) {
|
||||||
|
btnTextElement.textContent = "Resume";
|
||||||
|
} else if (!this.isDownloading) {
|
||||||
|
btnTextElement.textContent = "Download";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async startDownload() {
|
async startDownload() {
|
||||||
if (this.isDownloading) {
|
if (this.isDownloading) {
|
||||||
showToast('Download already in progress', 'warning');
|
showToast('Download already in progress', 'warning');
|
||||||
@@ -176,7 +177,7 @@ class ExampleImagesManager {
|
|||||||
const outputDir = document.getElementById('exampleImagesPath').value || '';
|
const outputDir = document.getElementById('exampleImagesPath').value || '';
|
||||||
|
|
||||||
if (!outputDir) {
|
if (!outputDir) {
|
||||||
showToast('Please select a download location first', 'warning');
|
showToast('Please enter a download location first', 'warning');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,11 +204,9 @@ class ExampleImagesManager {
|
|||||||
this.updateUI(data.status);
|
this.updateUI(data.status);
|
||||||
this.showProgressPanel();
|
this.showProgressPanel();
|
||||||
this.startProgressUpdates();
|
this.startProgressUpdates();
|
||||||
|
this.updateDownloadButtonText();
|
||||||
showToast('Example images download started', 'success');
|
showToast('Example images download started', 'success');
|
||||||
|
|
||||||
// Hide the start button, show resume button
|
|
||||||
document.getElementById('startExampleDownloadBtn').style.display = 'none';
|
|
||||||
|
|
||||||
// Close settings modal
|
// Close settings modal
|
||||||
modalManager.closeModal('settingsModal');
|
modalManager.closeModal('settingsModal');
|
||||||
} else {
|
} else {
|
||||||
@@ -236,10 +235,8 @@ class ExampleImagesManager {
|
|||||||
document.getElementById('downloadStatusText').textContent = 'Paused';
|
document.getElementById('downloadStatusText').textContent = 'Paused';
|
||||||
document.getElementById('pauseExampleDownloadBtn').innerHTML = '<i class="fas fa-play"></i>';
|
document.getElementById('pauseExampleDownloadBtn').innerHTML = '<i class="fas fa-play"></i>';
|
||||||
document.getElementById('pauseExampleDownloadBtn').onclick = () => this.resumeDownload();
|
document.getElementById('pauseExampleDownloadBtn').onclick = () => this.resumeDownload();
|
||||||
|
this.updateDownloadButtonText();
|
||||||
showToast('Download paused', 'info');
|
showToast('Download paused', 'info');
|
||||||
|
|
||||||
// Show resume button in settings too
|
|
||||||
document.getElementById('resumeExampleDownloadBtn').style.display = 'block';
|
|
||||||
} else {
|
} else {
|
||||||
showToast(data.error || 'Failed to pause download', 'error');
|
showToast(data.error || 'Failed to pause download', 'error');
|
||||||
}
|
}
|
||||||
@@ -266,10 +263,8 @@ class ExampleImagesManager {
|
|||||||
document.getElementById('downloadStatusText').textContent = 'Downloading';
|
document.getElementById('downloadStatusText').textContent = 'Downloading';
|
||||||
document.getElementById('pauseExampleDownloadBtn').innerHTML = '<i class="fas fa-pause"></i>';
|
document.getElementById('pauseExampleDownloadBtn').innerHTML = '<i class="fas fa-pause"></i>';
|
||||||
document.getElementById('pauseExampleDownloadBtn').onclick = () => this.pauseDownload();
|
document.getElementById('pauseExampleDownloadBtn').onclick = () => this.pauseDownload();
|
||||||
|
this.updateDownloadButtonText();
|
||||||
showToast('Download resumed', 'success');
|
showToast('Download resumed', 'success');
|
||||||
|
|
||||||
// Hide resume button in settings
|
|
||||||
document.getElementById('resumeExampleDownloadBtn').style.display = 'none';
|
|
||||||
} else {
|
} else {
|
||||||
showToast(data.error || 'Failed to resume download', 'error');
|
showToast(data.error || 'Failed to resume download', 'error');
|
||||||
}
|
}
|
||||||
@@ -298,6 +293,10 @@ class ExampleImagesManager {
|
|||||||
|
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
this.isDownloading = data.is_downloading;
|
this.isDownloading = data.is_downloading;
|
||||||
|
this.isPaused = data.status.status === 'paused';
|
||||||
|
|
||||||
|
// Update download button text
|
||||||
|
this.updateDownloadButtonText();
|
||||||
|
|
||||||
if (this.isDownloading) {
|
if (this.isDownloading) {
|
||||||
this.updateUI(data.status);
|
this.updateUI(data.status);
|
||||||
@@ -313,10 +312,6 @@ class ExampleImagesManager {
|
|||||||
} else if (data.status.status === 'error') {
|
} else if (data.status.status === 'error') {
|
||||||
showToast('Example images download failed', 'error');
|
showToast('Example images download failed', 'error');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset UI
|
|
||||||
document.getElementById('startExampleDownloadBtn').style.display = 'block';
|
|
||||||
document.getElementById('resumeExampleDownloadBtn').style.display = 'none';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -325,21 +320,38 @@ class ExampleImagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateUI(status) {
|
updateUI(status) {
|
||||||
|
// Ensure progress panel exists
|
||||||
|
if (!this.progressPanel) {
|
||||||
|
this.progressPanel = document.getElementById('exampleImagesProgress');
|
||||||
|
if (!this.progressPanel) {
|
||||||
|
console.error('Progress panel element not found in DOM');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update status text
|
// Update status text
|
||||||
const statusText = document.getElementById('downloadStatusText');
|
const statusText = document.getElementById('downloadStatusText');
|
||||||
statusText.textContent = this.getStatusText(status.status);
|
if (statusText) {
|
||||||
|
statusText.textContent = this.getStatusText(status.status);
|
||||||
|
}
|
||||||
|
|
||||||
// Update progress counts and bar
|
// Update progress counts and bar
|
||||||
const progressCounts = document.getElementById('downloadProgressCounts');
|
const progressCounts = document.getElementById('downloadProgressCounts');
|
||||||
progressCounts.textContent = `${status.completed}/${status.total}`;
|
if (progressCounts) {
|
||||||
|
progressCounts.textContent = `${status.completed}/${status.total}`;
|
||||||
|
}
|
||||||
|
|
||||||
const progressBar = document.getElementById('downloadProgressBar');
|
const progressBar = document.getElementById('downloadProgressBar');
|
||||||
const progressPercent = status.total > 0 ? (status.completed / status.total) * 100 : 0;
|
if (progressBar) {
|
||||||
progressBar.style.width = `${progressPercent}%`;
|
const progressPercent = status.total > 0 ? (status.completed / status.total) * 100 : 0;
|
||||||
|
progressBar.style.width = `${progressPercent}%`;
|
||||||
|
}
|
||||||
|
|
||||||
// Update current model
|
// Update current model
|
||||||
const currentModel = document.getElementById('currentModelName');
|
const currentModel = document.getElementById('currentModelName');
|
||||||
currentModel.textContent = status.current_model || '-';
|
if (currentModel) {
|
||||||
|
currentModel.textContent = status.current_model || '-';
|
||||||
|
}
|
||||||
|
|
||||||
// Update time stats
|
// Update time stats
|
||||||
this.updateTimeStats(status);
|
this.updateTimeStats(status);
|
||||||
@@ -348,14 +360,21 @@ class ExampleImagesManager {
|
|||||||
this.updateErrors(status);
|
this.updateErrors(status);
|
||||||
|
|
||||||
// Update pause/resume button
|
// Update pause/resume button
|
||||||
if (status.status === 'paused') {
|
const pauseBtn = document.getElementById('pauseExampleDownloadBtn');
|
||||||
document.getElementById('pauseExampleDownloadBtn').innerHTML = '<i class="fas fa-play"></i>';
|
const resumeBtn = document.getElementById('resumeExampleDownloadBtn');
|
||||||
document.getElementById('pauseExampleDownloadBtn').onclick = () => this.resumeDownload();
|
|
||||||
document.getElementById('resumeExampleDownloadBtn').style.display = 'block';
|
if (pauseBtn) {
|
||||||
} else {
|
if (status.status === 'paused') {
|
||||||
document.getElementById('pauseExampleDownloadBtn').innerHTML = '<i class="fas fa-pause"></i>';
|
pauseBtn.innerHTML = '<i class="fas fa-play"></i>';
|
||||||
document.getElementById('pauseExampleDownloadBtn').onclick = () => this.pauseDownload();
|
pauseBtn.onclick = () => this.resumeDownload();
|
||||||
document.getElementById('resumeExampleDownloadBtn').style.display = 'none';
|
} else {
|
||||||
|
pauseBtn.innerHTML = '<i class="fas fa-pause"></i>';
|
||||||
|
pauseBtn.onclick = () => this.pauseDownload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resumeBtn) {
|
||||||
|
resumeBtn.style.display = status.status === 'paused' ? 'block' : 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,6 +382,8 @@ class ExampleImagesManager {
|
|||||||
const elapsedTime = document.getElementById('elapsedTime');
|
const elapsedTime = document.getElementById('elapsedTime');
|
||||||
const remainingTime = document.getElementById('remainingTime');
|
const remainingTime = document.getElementById('remainingTime');
|
||||||
|
|
||||||
|
if (!elapsedTime || !remainingTime) return;
|
||||||
|
|
||||||
// Calculate elapsed time
|
// Calculate elapsed time
|
||||||
let elapsed;
|
let elapsed;
|
||||||
if (status.start_time) {
|
if (status.start_time) {
|
||||||
@@ -389,6 +410,8 @@ class ExampleImagesManager {
|
|||||||
const errorContainer = document.getElementById('downloadErrorContainer');
|
const errorContainer = document.getElementById('downloadErrorContainer');
|
||||||
const errorList = document.getElementById('downloadErrors');
|
const errorList = document.getElementById('downloadErrors');
|
||||||
|
|
||||||
|
if (!errorContainer || !errorList) return;
|
||||||
|
|
||||||
if (status.errors && status.errors.length > 0) {
|
if (status.errors && status.errors.length > 0) {
|
||||||
// Show only the last 3 errors
|
// Show only the last 3 errors
|
||||||
const recentErrors = status.errors.slice(-3);
|
const recentErrors = status.errors.slice(-3);
|
||||||
@@ -425,22 +448,41 @@ class ExampleImagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showProgressPanel() {
|
showProgressPanel() {
|
||||||
|
// Ensure progress panel exists
|
||||||
|
if (!this.progressPanel) {
|
||||||
|
this.progressPanel = document.getElementById('exampleImagesProgress');
|
||||||
|
if (!this.progressPanel) {
|
||||||
|
console.error('Progress panel element not found in DOM');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
this.progressPanel.classList.add('visible');
|
this.progressPanel.classList.add('visible');
|
||||||
}
|
}
|
||||||
|
|
||||||
hideProgressPanel() {
|
hideProgressPanel() {
|
||||||
|
if (!this.progressPanel) {
|
||||||
|
this.progressPanel = document.getElementById('exampleImagesProgress');
|
||||||
|
if (!this.progressPanel) return;
|
||||||
|
}
|
||||||
this.progressPanel.classList.remove('visible');
|
this.progressPanel.classList.remove('visible');
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleProgressPanel() {
|
toggleProgressPanel() {
|
||||||
|
if (!this.progressPanel) {
|
||||||
|
this.progressPanel = document.getElementById('exampleImagesProgress');
|
||||||
|
if (!this.progressPanel) return;
|
||||||
|
}
|
||||||
|
|
||||||
this.progressPanel.classList.toggle('collapsed');
|
this.progressPanel.classList.toggle('collapsed');
|
||||||
|
|
||||||
// Update icon
|
// Update icon
|
||||||
const icon = document.querySelector('#collapseProgressBtn i');
|
const icon = document.querySelector('#collapseProgressBtn i');
|
||||||
if (this.progressPanel.classList.contains('collapsed')) {
|
if (icon) {
|
||||||
icon.className = 'fas fa-chevron-up';
|
if (this.progressPanel.classList.contains('collapsed')) {
|
||||||
} else {
|
icon.className = 'fas fa-chevron-up';
|
||||||
icon.className = 'fas fa-chevron-down';
|
} else {
|
||||||
|
icon.className = 'fas fa-chevron-down';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,15 +135,15 @@
|
|||||||
<div class="setting-info">
|
<div class="setting-info">
|
||||||
<label for="exampleImagesPath">Download Location</label>
|
<label for="exampleImagesPath">Download Location</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-control path-browser-control">
|
<div class="setting-control path-control">
|
||||||
<input type="text" id="exampleImagesPath" placeholder="Select a folder for example images" />
|
<input type="text" id="exampleImagesPath" placeholder="Enter folder path for example images" />
|
||||||
<button id="browseExampleImagesPath" class="browse-btn">
|
<button id="exampleImagesDownloadBtn" class="primary-btn">
|
||||||
<i class="fas fa-folder-open"></i> Browse
|
<i class="fas fa-download"></i> <span id="exampleDownloadBtnText">Download</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-help">
|
<div class="input-help">
|
||||||
Choose where to save example images downloaded from Civitai
|
Enter the folder path where example images from Civitai will be saved
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -164,17 +164,6 @@
|
|||||||
Optimize example images to reduce file size and improve loading speed
|
Optimize example images to reduce file size and improve loading speed
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-item">
|
|
||||||
<div class="setting-row download-buttons">
|
|
||||||
<button id="startExampleDownloadBtn" class="primary-btn disabled">
|
|
||||||
<i class="fas fa-download"></i> Download Example Images
|
|
||||||
</button>
|
|
||||||
<button id="resumeExampleDownloadBtn" class="primary-btn" style="display: none;">
|
|
||||||
<i class="fas fa-play"></i> Resume Download
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
<i class="fas fa-images"></i> Example Images Download
|
<i class="fas fa-images"></i> Example Images Download
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-panel-actions">
|
<div class="progress-panel-actions">
|
||||||
<button id="pauseExampleDownloadBtn" class="icon-button" onclick="exampleImagesManager.pauseDownload()">
|
<button id="pauseExampleDownloadBtn" class="icon-button">
|
||||||
<i class="fas fa-pause"></i>
|
<i class="fas fa-pause"></i>
|
||||||
</button>
|
</button>
|
||||||
<button id="collapseProgressBtn" class="icon-button" onclick="exampleImagesManager.toggleProgressPanel()">
|
<button id="collapseProgressBtn" class="icon-button">
|
||||||
<i class="fas fa-chevron-down"></i>
|
<i class="fas fa-chevron-down"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -46,3 +46,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Initialize button onclick handlers when DOM is fully loaded
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const pauseBtn = document.getElementById('pauseExampleDownloadBtn');
|
||||||
|
const collapseBtn = document.getElementById('collapseProgressBtn');
|
||||||
|
|
||||||
|
// Make window.exampleImagesManager globally available
|
||||||
|
if (window.exampleImagesManager === undefined && typeof exampleImagesManager !== 'undefined') {
|
||||||
|
window.exampleImagesManager = exampleImagesManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pauseBtn && window.exampleImagesManager) {
|
||||||
|
pauseBtn.onclick = () => window.exampleImagesManager.pauseDownload();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collapseBtn && window.exampleImagesManager) {
|
||||||
|
collapseBtn.onclick = () => {
|
||||||
|
if (window.exampleImagesManager.toggleProgressPanel) {
|
||||||
|
window.exampleImagesManager.toggleProgressPanel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user