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:
Will Miao
2026-08-27 18:07:28 +08:00
parent df34efafbc
commit 2bfb987312
9 changed files with 1228 additions and 382 deletions
+2 -1
View File
@@ -20,7 +20,7 @@ import { BulkContextMenu } from './components/ContextMenu/BulkContextMenu.js';
import { createPageContextMenu, createGlobalContextMenu } from './components/ContextMenu/index.js';
import { initializeEventManagement } from './utils/eventManagementInit.js';
import { civitaiBaseModelApi } from './api/civitaiBaseModelApi.js';
import { setDynamicBaseModels } from './utils/constants.js';
import { setDynamicBaseModels, BASE_MODELS_UPDATED_EVENT } from './utils/constants.js';
// Core application class
export class AppCore {
@@ -134,6 +134,7 @@ export class AppCore {
const result = await civitaiBaseModelApi.getBaseModels();
if (result && result.models) {
setDynamicBaseModels(result.models, result.last_updated);
window.dispatchEvent(new CustomEvent(BASE_MODELS_UPDATED_EVENT));
console.log(`AppCore: Loaded ${result.merged_count} base models (${result.hardcoded_count} hardcoded + ${result.remote_count} remote)`);
}
} catch (error) {