mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-08-28 16:31:28 -03:00
feat(models): add shared searchable base model picker and overhaul bulk base model modal
- Extract a shared BaseModelPicker (search, keyboard navigation, filename-based suggestions, dynamic API models such as MiniMax H3 under 'Other (API)') used by both the single-model metadata modal and the bulk base model modal - Rework the bulk base model modal into a dedicated inline-list layout: fixed modal size, sticky-free footer with app-standard modal-actions/primary-btn/cancel-btn buttons, and an inline option list that scrolls itself instead of an overlay dropdown covering the footer - Selecting an option in change mode now filters the list to the selection instead of resetting and scroll-jumping to it - Restore opaque sticky section headers in the bulk modal so scrolled items no longer bleed through
This commit is contained in:
@@ -6,7 +6,7 @@ import { modalManager } from './ModalManager.js';
|
||||
import { getModelApiClient, resetAndReload } from '../api/modelApiFactory.js';
|
||||
import { RecipeSidebarApiClient, updateRecipeMetadata, extractRecipeId } from '../api/recipeApi.js';
|
||||
import { MODEL_TYPES, MODEL_CONFIG } from '../api/apiConfig.js';
|
||||
import { BASE_MODEL_CATEGORIES } from '../utils/constants.js';
|
||||
import { createBaseModelPicker, inferBaseModelsFromFilepaths } from '../components/shared/BaseModelPicker.js';
|
||||
import { getPriorityTagSuggestions } from '../utils/priorityTagHelpers.js';
|
||||
import { eventManager } from '../utils/EventManager.js';
|
||||
import { translate } from '../utils/i18nHelpers.js';
|
||||
@@ -30,6 +30,10 @@ export class BulkManager {
|
||||
// toggleCardSelection, cleared in clearSelection.
|
||||
this.bulkAnchorFilepath = null;
|
||||
|
||||
// Bulk base model picker state
|
||||
this.bulkBaseModelPicker = null;
|
||||
this.bulkBaseModelValue = '';
|
||||
|
||||
// Drag detection properties
|
||||
this.dragThreshold = 5; // Pixels to move before considering it a drag
|
||||
this.dragDelayMs = 100; // Minimum hold time before a drag is treated as a marquee
|
||||
@@ -1830,47 +1834,35 @@ export class BulkManager {
|
||||
* Initialize bulk base model interface
|
||||
*/
|
||||
initializeBulkBaseModelInterface() {
|
||||
const select = document.getElementById('bulkBaseModelSelect');
|
||||
if (!select) return;
|
||||
const container = document.getElementById('bulkBaseModelPicker');
|
||||
if (!container) return;
|
||||
|
||||
// Clear existing options
|
||||
select.innerHTML = '';
|
||||
// Reset any previous picker instance
|
||||
this.cleanupBulkBaseModelModal();
|
||||
container.innerHTML = '';
|
||||
|
||||
// Add placeholder option
|
||||
const placeholderOption = document.createElement('option');
|
||||
placeholderOption.value = '';
|
||||
placeholderOption.textContent = 'Select a base model...';
|
||||
placeholderOption.disabled = true;
|
||||
placeholderOption.selected = true;
|
||||
select.appendChild(placeholderOption);
|
||||
|
||||
// Create option groups for better organization
|
||||
Object.entries(BASE_MODEL_CATEGORIES).forEach(([category, models]) => {
|
||||
const optgroup = document.createElement('optgroup');
|
||||
optgroup.label = category;
|
||||
|
||||
models.forEach(model => {
|
||||
const option = document.createElement('option');
|
||||
option.value = model;
|
||||
option.textContent = model;
|
||||
optgroup.appendChild(option);
|
||||
});
|
||||
|
||||
select.appendChild(optgroup);
|
||||
const suggestions = inferBaseModelsFromFilepaths(Array.from(state.selectedModels));
|
||||
this.bulkBaseModelValue = '';
|
||||
this.bulkBaseModelPicker = createBaseModelPicker({
|
||||
suggestions,
|
||||
mode: 'change',
|
||||
onChange: (value) => {
|
||||
this.bulkBaseModelValue = value;
|
||||
},
|
||||
});
|
||||
container.appendChild(this.bulkBaseModelPicker.element);
|
||||
this.bulkBaseModelPicker.element.querySelector('.base-model-search-input')?.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save bulk base model changes
|
||||
*/
|
||||
async saveBulkBaseModel() {
|
||||
const select = document.getElementById('bulkBaseModelSelect');
|
||||
if (!select || !select.value) {
|
||||
const newBaseModel = (this.bulkBaseModelValue || this.bulkBaseModelPicker?.getValue() || '').trim();
|
||||
if (!newBaseModel) {
|
||||
showToast('toast.models.baseModelNotSelected', {}, 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const newBaseModel = select.value;
|
||||
const selectedCount = state.selectedModels.size;
|
||||
|
||||
if (selectedCount === 0) {
|
||||
@@ -1938,9 +1930,14 @@ export class BulkManager {
|
||||
* Cleanup bulk base model modal
|
||||
*/
|
||||
cleanupBulkBaseModelModal() {
|
||||
const select = document.getElementById('bulkBaseModelSelect');
|
||||
if (select) {
|
||||
select.innerHTML = '';
|
||||
if (this.bulkBaseModelPicker) {
|
||||
this.bulkBaseModelPicker.destroy();
|
||||
this.bulkBaseModelPicker = null;
|
||||
}
|
||||
this.bulkBaseModelValue = '';
|
||||
const container = document.getElementById('bulkBaseModelPicker');
|
||||
if (container) {
|
||||
container.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user