mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
refactor: enhance bulk metadata refresh functionality and update UI components
This commit is contained in:
@@ -45,7 +45,7 @@
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
.update-progress-bar {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
@@ -53,7 +53,7 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .progress-bar {
|
||||
[data-theme="dark"] .update-progress-bar {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
|
||||
@@ -477,6 +477,104 @@ class ModelApiClient {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CivitAI metadata for multiple models with progress tracking
|
||||
*/
|
||||
async refreshBulkModelMetadata(filePaths) {
|
||||
if (!filePaths || filePaths.length === 0) {
|
||||
throw new Error('No file paths provided');
|
||||
}
|
||||
|
||||
const totalItems = filePaths.length;
|
||||
let processedCount = 0;
|
||||
let successCount = 0;
|
||||
let failedItems = [];
|
||||
|
||||
const progressController = state.loadingManager.showEnhancedProgress('Starting metadata refresh...');
|
||||
|
||||
try {
|
||||
// Process files sequentially to avoid overwhelming the API
|
||||
for (let i = 0; i < filePaths.length; i++) {
|
||||
const filePath = filePaths[i];
|
||||
const fileName = filePath.split('/').pop();
|
||||
|
||||
try {
|
||||
const overallProgress = Math.floor((i / totalItems) * 100);
|
||||
progressController.updateProgress(
|
||||
overallProgress,
|
||||
fileName,
|
||||
`Processing ${i + 1}/${totalItems}: ${fileName}`
|
||||
);
|
||||
|
||||
const response = await fetch(this.apiConfig.endpoints.fetchCivitai, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ file_path: filePath })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
if (data.metadata && state.virtualScroller) {
|
||||
state.virtualScroller.updateSingleItem(filePath, data.metadata);
|
||||
}
|
||||
successCount++;
|
||||
} else {
|
||||
throw new Error(data.error || 'Failed to refresh metadata');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error refreshing metadata for ${fileName}:`, error);
|
||||
failedItems.push({ filePath, fileName, error: error.message });
|
||||
}
|
||||
|
||||
processedCount++;
|
||||
}
|
||||
|
||||
// Show completion message
|
||||
let completionMessage;
|
||||
if (successCount === totalItems) {
|
||||
completionMessage = `Successfully refreshed all ${successCount} ${this.apiConfig.config.displayName}s`;
|
||||
showToast(completionMessage, 'success');
|
||||
} else if (successCount > 0) {
|
||||
completionMessage = `Refreshed ${successCount} of ${totalItems} ${this.apiConfig.config.displayName}s`;
|
||||
showToast(completionMessage, 'warning');
|
||||
|
||||
if (failedItems.length > 0) {
|
||||
const failureMessage = failedItems.length <= 3
|
||||
? failedItems.map(item => `${item.fileName}: ${item.error}`).join('\n')
|
||||
: failedItems.slice(0, 3).map(item => `${item.fileName}: ${item.error}`).join('\n') +
|
||||
`\n(and ${failedItems.length - 3} more)`;
|
||||
showToast(`Failed refreshes:\n${failureMessage}`, 'warning', 6000);
|
||||
}
|
||||
} else {
|
||||
completionMessage = `Failed to refresh metadata for any ${this.apiConfig.config.displayName}s`;
|
||||
showToast(completionMessage, 'error');
|
||||
}
|
||||
|
||||
await progressController.complete(completionMessage);
|
||||
|
||||
return {
|
||||
success: successCount > 0,
|
||||
total: totalItems,
|
||||
processed: processedCount,
|
||||
successful: successCount,
|
||||
failed: failedItems.length,
|
||||
errors: failedItems
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error in bulk metadata refresh:', error);
|
||||
showToast(`Failed to refresh metadata: ${error.message}`, 'error');
|
||||
await progressController.complete('Operation failed');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a single model to target path
|
||||
* @returns {string|null} - The new file path if moved, null if not moved
|
||||
|
||||
@@ -2,6 +2,7 @@ import { state } from '../state/index.js';
|
||||
import { showToast, copyToClipboard, sendLoraToWorkflow } from '../utils/uiHelpers.js';
|
||||
import { updateCardsForBulkMode } from '../components/shared/ModelCard.js';
|
||||
import { modalManager } from './ModalManager.js';
|
||||
import { getModelApiClient } from '../api/baseModelApi.js';
|
||||
|
||||
export class BulkManager {
|
||||
constructor() {
|
||||
@@ -560,6 +561,55 @@ export class BulkManager {
|
||||
this.updateThumbnailStrip();
|
||||
}
|
||||
}
|
||||
|
||||
// Add method to refresh metadata for all selected models
|
||||
async refreshAllMetadata() {
|
||||
if (state.selectedLoras.size === 0) {
|
||||
showToast('No models selected', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Get the API client for the current model type
|
||||
const apiClient = getModelApiClient();
|
||||
|
||||
// Convert Set to Array for processing
|
||||
const filePaths = Array.from(state.selectedLoras);
|
||||
|
||||
// Call the bulk refresh method
|
||||
const result = await apiClient.refreshBulkModelMetadata(filePaths);
|
||||
|
||||
if (result.success) {
|
||||
// Update the metadata cache for successfully refreshed items
|
||||
for (const filepath of state.selectedLoras) {
|
||||
const metadata = state.loraMetadataCache.get(filepath);
|
||||
if (metadata) {
|
||||
// Find the corresponding card to get updated data
|
||||
const card = document.querySelector(`.model-card[data-filepath="${filepath}"]`);
|
||||
if (card) {
|
||||
state.loraMetadataCache.set(filepath, {
|
||||
...metadata,
|
||||
fileName: card.dataset.file_name,
|
||||
usageTips: card.dataset.usage_tips,
|
||||
previewUrl: this.getCardPreviewUrl(card),
|
||||
isVideo: this.isCardPreviewVideo(card),
|
||||
modelName: card.dataset.name
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update thumbnail strip if visible
|
||||
if (this.isStripVisible) {
|
||||
this.updateThumbnailStrip();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error during bulk metadata refresh:', error);
|
||||
showToast('Failed to refresh metadata', 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a singleton instance
|
||||
|
||||
@@ -145,6 +145,28 @@ export class LoadingManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Enhanced progress display without callback pattern
|
||||
showEnhancedProgress(message = 'Processing...') {
|
||||
this.show(message, 0);
|
||||
|
||||
// Return update functions
|
||||
return {
|
||||
updateProgress: (percent, currentItem = '', statusMessage = '') => {
|
||||
this.setProgress(percent);
|
||||
if (statusMessage) {
|
||||
this.setStatus(statusMessage);
|
||||
}
|
||||
},
|
||||
|
||||
complete: async (completionMessage = 'Complete') => {
|
||||
this.setProgress(100);
|
||||
this.setStatus(completionMessage);
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
this.hide();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
showSimpleLoading(message = 'Loading...') {
|
||||
this.overlay.style.display = 'flex';
|
||||
this.progressBar.style.display = 'none';
|
||||
@@ -154,4 +176,4 @@ export class LoadingManager {
|
||||
restoreProgressBar() {
|
||||
this.progressBar.style.display = 'block';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,6 +125,9 @@
|
||||
<button onclick="bulkManager.copyAllLorasSyntax()" title="Copy all selected LoRAs syntax">
|
||||
<i class="fas fa-copy"></i> Copy All
|
||||
</button>
|
||||
<button onclick="bulkManager.refreshAllMetadata()" title="Refresh CivitAI metadata for selected models">
|
||||
<i class="fas fa-sync-alt"></i> Refresh All
|
||||
</button>
|
||||
<button onclick="moveManager.showMoveModal('bulk')" title="Move selected LoRAs to folder">
|
||||
<i class="fas fa-folder-open"></i> Move All
|
||||
</button>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<div class="update-progress" id="updateProgress" style="display: none;">
|
||||
<div class="progress-info">
|
||||
<div class="progress-text" id="updateProgressText">Preparing update...</div>
|
||||
<div class="progress-bar">
|
||||
<div class="update-progress-bar">
|
||||
<div class="progress-fill" id="updateProgressFill"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user