mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 15:15:44 -03:00
Refactor API structure to unify model operations
- Introduced MODEL_TYPES and MODEL_CONFIG for centralized model type management. - Created a unified API client for checkpoints and loras to streamline operations. - Updated all API calls in checkpointApi.js and loraApi.js to use the new client. - Simplified context menus and model card operations to leverage the unified API client. - Enhanced state management to accommodate new model types and their configurations. - Added virtual scrolling functions for recipes and improved loading states. - Refactored modal utilities to handle model exclusion and deletion generically. - Improved error handling and user feedback across various operations.
This commit is contained in:
@@ -1,131 +1,35 @@
|
||||
import {
|
||||
fetchModelsPage,
|
||||
resetAndReloadWithVirtualScroll,
|
||||
loadMoreWithVirtualScroll,
|
||||
refreshModels as baseRefreshModels,
|
||||
deleteModel as baseDeleteModel,
|
||||
replaceModelPreview,
|
||||
fetchCivitaiMetadata,
|
||||
refreshSingleModelMetadata,
|
||||
excludeModel as baseExcludeModel
|
||||
} from './baseModelApi.js';
|
||||
import { state } from '../state/index.js';
|
||||
import { createModelApiClient } from './baseModelApi.js';
|
||||
import { MODEL_TYPES } from './apiConfig.js';
|
||||
|
||||
/**
|
||||
* Save model metadata to the server
|
||||
* @param {string} filePath - File path
|
||||
* @param {Object} data - Data to save
|
||||
* @returns {Promise} Promise of the save operation
|
||||
*/
|
||||
export async function saveModelMetadata(filePath, data) {
|
||||
try {
|
||||
// Show loading indicator
|
||||
state.loadingManager.showSimpleLoading('Saving metadata...');
|
||||
|
||||
const response = await fetch('/api/loras/save-metadata', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
file_path: filePath,
|
||||
...data
|
||||
})
|
||||
});
|
||||
// Create LoRA-specific API client
|
||||
const loraApiClient = createModelApiClient(MODEL_TYPES.LORA);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to save metadata');
|
||||
}
|
||||
// Export all common operations using the unified client
|
||||
export const deleteModel = (filePath) => loraApiClient.deleteModel(filePath);
|
||||
export const excludeLora = (filePath) => loraApiClient.excludeModel(filePath);
|
||||
export const renameLoraFile = (filePath, newFileName) => loraApiClient.renameModelFile(filePath, newFileName);
|
||||
export const replacePreview = (filePath) => loraApiClient.replaceModelPreview(filePath);
|
||||
export const saveModelMetadata = (filePath, data) => loraApiClient.saveModelMetadata(filePath, data);
|
||||
export const refreshLoras = (fullRebuild = false) => loraApiClient.refreshModels(fullRebuild);
|
||||
export const refreshSingleLoraMetadata = (filePath) => loraApiClient.refreshSingleModelMetadata(filePath);
|
||||
export const fetchCivitai = (resetAndReloadFunction) => loraApiClient.fetchCivitaiMetadata(resetAndReloadFunction);
|
||||
|
||||
// Update the virtual scroller with the new data
|
||||
state.virtualScroller.updateSingleItem(filePath, data);
|
||||
|
||||
return response.json();
|
||||
} finally {
|
||||
// Always hide the loading indicator when done
|
||||
state.loadingManager.hide();
|
||||
}
|
||||
}
|
||||
// Pagination functions
|
||||
export const fetchLorasPage = (page = 1, pageSize = 100) => loraApiClient.fetchModelsPage(page, pageSize);
|
||||
|
||||
/**
|
||||
* Exclude a lora model from being shown in the UI
|
||||
* @param {string} filePath - File path of the model to exclude
|
||||
* @returns {Promise<boolean>} Promise resolving to success status
|
||||
*/
|
||||
export async function excludeLora(filePath) {
|
||||
return baseExcludeModel(filePath, 'lora');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load more loras with pagination - updated to work with VirtualScroller
|
||||
* @param {boolean} resetPage - Whether to reset to the first page
|
||||
* @param {boolean} updateFolders - Whether to update folder tags
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
// Virtual scrolling operations
|
||||
export async function loadMoreLoras(resetPage = false, updateFolders = false) {
|
||||
return loadMoreWithVirtualScroll({
|
||||
modelType: 'lora',
|
||||
resetPage,
|
||||
updateFolders,
|
||||
fetchPageFunction: fetchLorasPage
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch loras with pagination for virtual scrolling
|
||||
* @param {number} page - Page number to fetch
|
||||
* @param {number} pageSize - Number of items per page
|
||||
* @returns {Promise<Object>} Object containing items, total count, and pagination info
|
||||
*/
|
||||
export async function fetchLorasPage(page = 1, pageSize = 100) {
|
||||
return fetchModelsPage({
|
||||
modelType: 'lora',
|
||||
page,
|
||||
pageSize,
|
||||
endpoint: '/api/loras'
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchCivitai() {
|
||||
return fetchCivitaiMetadata({
|
||||
modelType: 'lora',
|
||||
fetchEndpoint: '/api/loras/fetch-all-civitai',
|
||||
resetAndReloadFunction: resetAndReload
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteModel(filePath) {
|
||||
return baseDeleteModel(filePath, 'lora');
|
||||
}
|
||||
|
||||
export async function replacePreview(filePath) {
|
||||
return replaceModelPreview(filePath, 'lora');
|
||||
return loraApiClient.loadMoreWithVirtualScroll(resetPage, updateFolders);
|
||||
}
|
||||
|
||||
export async function resetAndReload(updateFolders = false) {
|
||||
return resetAndReloadWithVirtualScroll({
|
||||
modelType: 'lora',
|
||||
updateFolders,
|
||||
fetchPageFunction: fetchLorasPage
|
||||
});
|
||||
}
|
||||
|
||||
export async function refreshLoras(fullRebuild = false) {
|
||||
return baseRefreshModels({
|
||||
modelType: 'lora',
|
||||
scanEndpoint: '/api/loras/scan',
|
||||
resetAndReloadFunction: resetAndReload,
|
||||
fullRebuild: fullRebuild
|
||||
});
|
||||
}
|
||||
|
||||
export async function refreshSingleLoraMetadata(filePath) {
|
||||
await refreshSingleModelMetadata(filePath, 'lora');
|
||||
return loraApiClient.resetAndReloadWithVirtualScroll(updateFolders);
|
||||
}
|
||||
|
||||
// LoRA-specific functions that don't have common equivalents
|
||||
export async function fetchModelDescription(modelId, filePath) {
|
||||
try {
|
||||
const response = await fetch(`/api/loras/model-description?model_id=${modelId}&file_path=${encodeURIComponent(filePath)}`);
|
||||
const response = await fetch(`${loraApiClient.apiConfig.endpoints.specific.modelDescription}?model_id=${modelId}&file_path=${encodeURIComponent(filePath)}`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch model description: ${response.statusText}`);
|
||||
@@ -138,38 +42,47 @@ export async function fetchModelDescription(modelId, filePath) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename a LoRA file
|
||||
* @param {string} filePath - Current file path
|
||||
* @param {string} newFileName - New file name (without path)
|
||||
* @returns {Promise<Object>} - Promise that resolves with the server response
|
||||
*/
|
||||
export async function renameLoraFile(filePath, newFileName) {
|
||||
// Move operations (LoRA-specific)
|
||||
export async function moveModel(filePath, targetPath) {
|
||||
try {
|
||||
// Show loading indicator
|
||||
state.loadingManager.showSimpleLoading('Renaming LoRA file...');
|
||||
|
||||
const response = await fetch('/api/loras/rename', {
|
||||
const response = await fetch(loraApiClient.apiConfig.endpoints.specific.moveModel, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
file_path: filePath,
|
||||
new_file_name: newFileName
|
||||
target_path: targetPath
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server returned ${response.status}: ${response.statusText}`);
|
||||
throw new Error('Failed to move model');
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Error renaming LoRA file:', error);
|
||||
console.error('Error moving model:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function moveModelsBulk(filePaths, targetPath) {
|
||||
try {
|
||||
const response = await fetch(loraApiClient.apiConfig.endpoints.specific.moveBulk, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
file_paths: filePaths,
|
||||
target_path: targetPath
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to move models');
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Error moving models in bulk:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
// Hide loading indicator
|
||||
state.loadingManager.hide();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user