mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 07:05:43 -03:00
feat(example_images): add dedicated folder check and update settings handling for example images path, see #431
This commit is contained in:
@@ -4,6 +4,7 @@ import sys
|
|||||||
import threading
|
import threading
|
||||||
import asyncio
|
import asyncio
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import re
|
||||||
from server import PromptServer # type: ignore
|
from server import PromptServer # type: ignore
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from ..services.settings_manager import settings
|
from ..services.settings_manager import settings
|
||||||
@@ -85,6 +86,54 @@ node_registry = NodeRegistry()
|
|||||||
class MiscRoutes:
|
class MiscRoutes:
|
||||||
"""Miscellaneous routes for various utility functions"""
|
"""Miscellaneous routes for various utility functions"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_dedicated_example_images_folder(folder_path):
|
||||||
|
"""
|
||||||
|
Check if a folder is a dedicated example images folder.
|
||||||
|
|
||||||
|
A dedicated folder should either be:
|
||||||
|
1. Empty
|
||||||
|
2. Only contain .download_progress.json file and/or folders with valid SHA256 hash names (64 hex characters)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
folder_path (str): Path to the folder to check
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the folder is dedicated, False otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if not os.path.exists(folder_path) or not os.path.isdir(folder_path):
|
||||||
|
return False
|
||||||
|
|
||||||
|
items = os.listdir(folder_path)
|
||||||
|
|
||||||
|
# Empty folder is considered dedicated
|
||||||
|
if not items:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Check each item in the folder
|
||||||
|
for item in items:
|
||||||
|
item_path = os.path.join(folder_path, item)
|
||||||
|
|
||||||
|
# Allow .download_progress.json file
|
||||||
|
if item == '.download_progress.json' and os.path.isfile(item_path):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Allow folders with valid SHA256 hash names (64 hex characters)
|
||||||
|
if os.path.isdir(item_path):
|
||||||
|
# Check if the folder name is a valid SHA256 hash
|
||||||
|
if re.match(r'^[a-fA-F0-9]{64}$', item):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# If we encounter anything else, it's not a dedicated folder
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error checking if folder is dedicated: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def setup_routes(app):
|
def setup_routes(app):
|
||||||
"""Register miscellaneous routes"""
|
"""Register miscellaneous routes"""
|
||||||
@@ -180,7 +229,7 @@ class MiscRoutes:
|
|||||||
if value == settings.get(key):
|
if value == settings.get(key):
|
||||||
# No change, skip
|
# No change, skip
|
||||||
continue
|
continue
|
||||||
# Special handling for example_images_path - verify path exists
|
# Special handling for example_images_path - verify path exists and is dedicated
|
||||||
if key == 'example_images_path' and value:
|
if key == 'example_images_path' and value:
|
||||||
if not os.path.exists(value):
|
if not os.path.exists(value):
|
||||||
return web.json_response({
|
return web.json_response({
|
||||||
@@ -188,6 +237,13 @@ class MiscRoutes:
|
|||||||
'error': f"Path does not exist: {value}"
|
'error': f"Path does not exist: {value}"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Check if folder is dedicated for example images
|
||||||
|
if not MiscRoutes.is_dedicated_example_images_folder(value):
|
||||||
|
return web.json_response({
|
||||||
|
'success': False,
|
||||||
|
'error': "Please set a dedicated folder for example images."
|
||||||
|
})
|
||||||
|
|
||||||
# Path changed - server restart required for new path to take effect
|
# 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:
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ class DownloadManager:
|
|||||||
|
|
||||||
Expects a JSON body with:
|
Expects a JSON body with:
|
||||||
{
|
{
|
||||||
"output_dir": "path/to/output", # Base directory to save example images
|
|
||||||
"optimize": true, # Whether to optimize images (default: true)
|
"optimize": true, # Whether to optimize images (default: true)
|
||||||
"model_types": ["lora", "checkpoint"], # Model types to process (default: both)
|
"model_types": ["lora", "checkpoint"], # Model types to process (default: both)
|
||||||
"delay": 1.0 # Delay between downloads to avoid rate limiting (default: 1.0)
|
"delay": 1.0, # Delay between downloads to avoid rate limiting (default: 1.0)
|
||||||
|
"auto_mode": false # Flag to indicate automatic download (default: false)
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
global download_task, is_downloading, download_progress
|
global download_task, is_downloading, download_progress
|
||||||
@@ -64,16 +64,30 @@ class DownloadManager:
|
|||||||
try:
|
try:
|
||||||
# Parse the request body
|
# Parse the request body
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
output_dir = data.get('output_dir')
|
auto_mode = data.get('auto_mode', False)
|
||||||
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', 0.2)) # Default to 0.2 seconds
|
delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds
|
||||||
|
|
||||||
|
# Get output directory from settings
|
||||||
|
from ..services.service_registry import ServiceRegistry
|
||||||
|
settings_manager = await ServiceRegistry.get_settings_manager()
|
||||||
|
output_dir = settings_manager.get('example_images_path')
|
||||||
|
|
||||||
if not output_dir:
|
if not output_dir:
|
||||||
return web.json_response({
|
error_msg = 'Example images path not configured in settings'
|
||||||
'success': False,
|
if auto_mode:
|
||||||
'error': 'Missing output_dir parameter'
|
# For auto mode, just log and return success to avoid showing error toasts
|
||||||
}, status=400)
|
logger.debug(error_msg)
|
||||||
|
return web.json_response({
|
||||||
|
'success': True,
|
||||||
|
'message': 'Example images path not configured, skipping auto download'
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
return web.json_response({
|
||||||
|
'success': False,
|
||||||
|
'error': error_msg
|
||||||
|
}, status=400)
|
||||||
|
|
||||||
# Create the output directory
|
# Create the output directory
|
||||||
os.makedirs(output_dir, exist_ok=True)
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
@@ -426,7 +440,6 @@ class DownloadManager:
|
|||||||
Expects a JSON body with:
|
Expects a JSON body with:
|
||||||
{
|
{
|
||||||
"model_hashes": ["hash1", "hash2", ...], # List of model hashes to download
|
"model_hashes": ["hash1", "hash2", ...], # List of model hashes to download
|
||||||
"output_dir": "path/to/output", # Base directory to save example images
|
|
||||||
"optimize": true, # Whether to optimize images (default: true)
|
"optimize": true, # Whether to optimize images (default: true)
|
||||||
"model_types": ["lora", "checkpoint"], # Model types to process (default: both)
|
"model_types": ["lora", "checkpoint"], # Model types to process (default: both)
|
||||||
"delay": 1.0 # Delay between downloads (default: 1.0)
|
"delay": 1.0 # Delay between downloads (default: 1.0)
|
||||||
@@ -444,7 +457,6 @@ class DownloadManager:
|
|||||||
# Parse the request body
|
# Parse the request body
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
model_hashes = data.get('model_hashes', [])
|
model_hashes = data.get('model_hashes', [])
|
||||||
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', 0.2)) # Default to 0.2 seconds
|
delay = float(data.get('delay', 0.2)) # Default to 0.2 seconds
|
||||||
@@ -455,10 +467,15 @@ class DownloadManager:
|
|||||||
'error': 'Missing model_hashes parameter'
|
'error': 'Missing model_hashes parameter'
|
||||||
}, status=400)
|
}, status=400)
|
||||||
|
|
||||||
|
# Get output directory from settings
|
||||||
|
from ..services.service_registry import ServiceRegistry
|
||||||
|
settings_manager = await ServiceRegistry.get_settings_manager()
|
||||||
|
output_dir = settings_manager.get('example_images_path')
|
||||||
|
|
||||||
if not output_dir:
|
if not output_dir:
|
||||||
return web.json_response({
|
return web.json_response({
|
||||||
'success': False,
|
'success': False,
|
||||||
'error': 'Missing output_dir parameter'
|
'error': 'Example images path not configured in settings'
|
||||||
}, status=400)
|
}, status=400)
|
||||||
|
|
||||||
# Create the output directory
|
# Create the output directory
|
||||||
|
|||||||
@@ -100,9 +100,7 @@ export class ExampleImagesManager {
|
|||||||
this.updateDownloadButtonState(hasPath);
|
this.updateDownloadButtonState(hasPath);
|
||||||
try {
|
try {
|
||||||
await settingsManager.saveSetting('example_images_path', pathInput.value);
|
await settingsManager.saveSetting('example_images_path', pathInput.value);
|
||||||
if (hasPath) {
|
|
||||||
showToast('toast.exampleImages.pathUpdated', {}, 'success');
|
showToast('toast.exampleImages.pathUpdated', {}, 'success');
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to update example images path:', error);
|
console.error('Failed to update example images path:', error);
|
||||||
showToast('toast.exampleImages.pathUpdateFailed', { message: error.message }, 'error');
|
showToast('toast.exampleImages.pathUpdateFailed', { message: error.message }, 'error');
|
||||||
@@ -227,13 +225,6 @@ export class ExampleImagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const outputDir = document.getElementById('exampleImagesPath').value || '';
|
|
||||||
|
|
||||||
if (!outputDir) {
|
|
||||||
showToast('toast.exampleImages.enterLocationFirst', {}, 'warning');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const optimize = state.global.settings.optimizeExampleImages;
|
const optimize = state.global.settings.optimizeExampleImages;
|
||||||
|
|
||||||
const response = await fetch('/api/lm/download-example-images', {
|
const response = await fetch('/api/lm/download-example-images', {
|
||||||
@@ -242,7 +233,6 @@ export class ExampleImagesManager {
|
|||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
output_dir: outputDir,
|
|
||||||
optimize: optimize,
|
optimize: optimize,
|
||||||
model_types: ['lora', 'checkpoint', 'embedding'] // Example types, adjust as needed
|
model_types: ['lora', 'checkpoint', 'embedding'] // Example types, adjust as needed
|
||||||
})
|
})
|
||||||
@@ -691,9 +681,8 @@ export class ExampleImagesManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if download path is set
|
// Check if download path is set in settings
|
||||||
const pathInput = document.getElementById('exampleImagesPath');
|
if (!state.global.settings.example_images_path) {
|
||||||
if (!pathInput || !pathInput.value.trim()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,7 +713,6 @@ export class ExampleImagesManager {
|
|||||||
try {
|
try {
|
||||||
console.log('Performing auto download check...');
|
console.log('Performing auto download check...');
|
||||||
|
|
||||||
const outputDir = document.getElementById('exampleImagesPath').value;
|
|
||||||
const optimize = state.global.settings.optimizeExampleImages;
|
const optimize = state.global.settings.optimizeExampleImages;
|
||||||
|
|
||||||
const response = await fetch('/api/lm/download-example-images', {
|
const response = await fetch('/api/lm/download-example-images', {
|
||||||
@@ -733,7 +721,6 @@ export class ExampleImagesManager {
|
|||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
output_dir: outputDir,
|
|
||||||
optimize: optimize,
|
optimize: optimize,
|
||||||
model_types: ['lora', 'checkpoint', 'embedding'],
|
model_types: ['lora', 'checkpoint', 'embedding'],
|
||||||
auto_mode: true // Flag to indicate this is an automatic download
|
auto_mode: true // Flag to indicate this is an automatic download
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ export class SettingsManager {
|
|||||||
proxy_password: '',
|
proxy_password: '',
|
||||||
example_images_path: '',
|
example_images_path: '',
|
||||||
optimizeExampleImages: true,
|
optimizeExampleImages: true,
|
||||||
autoDownloadExampleImages: true
|
autoDownloadExampleImages: false
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.keys(backendDefaults).forEach(key => {
|
Object.keys(backendDefaults).forEach(key => {
|
||||||
@@ -972,10 +972,6 @@ export class SettingsManager {
|
|||||||
await this.saveSetting('default_embedding_root', value);
|
await this.saveSetting('default_embedding_root', value);
|
||||||
} else if (settingKey === 'display_density') {
|
} else if (settingKey === 'display_density') {
|
||||||
await this.saveSetting('displayDensity', value);
|
await this.saveSetting('displayDensity', value);
|
||||||
|
|
||||||
// Also update compactMode for backwards compatibility
|
|
||||||
state.global.settings.compactMode = (value !== 'default');
|
|
||||||
this.saveFrontendSettingsToStorage();
|
|
||||||
} else if (settingKey === 'card_info_display') {
|
} else if (settingKey === 'card_info_display') {
|
||||||
await this.saveSetting('cardInfoDisplay', value);
|
await this.saveSetting('cardInfoDisplay', value);
|
||||||
} else if (settingKey === 'proxy_type') {
|
} else if (settingKey === 'proxy_type') {
|
||||||
|
|||||||
Reference in New Issue
Block a user