From d13b1a83ad74264fe51abab3f116506bd9e7e7d5 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 12 May 2025 16:44:45 +0800 Subject: [PATCH] checkpoint --- static/js/api/loraApi.js | 140 +++++++++++++++--- static/js/components/LoraCard.js | 7 +- static/js/components/controls/PageControls.js | 2 +- 3 files changed, 128 insertions(+), 21 deletions(-) diff --git a/static/js/api/loraApi.js b/static/js/api/loraApi.js index 19505056..1df4d2f6 100644 --- a/static/js/api/loraApi.js +++ b/static/js/api/loraApi.js @@ -10,6 +10,8 @@ import { refreshSingleModelMetadata, excludeModel as baseExcludeModel } from './baseModelApi.js'; +import { state, getCurrentPageState } from '../state/index.js'; +import { showToast } from '../utils/uiHelpers.js'; /** * Save model metadata to the server @@ -45,14 +47,66 @@ 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} + */ export async function loadMoreLoras(resetPage = false, updateFolders = false) { - return loadMoreModels({ - resetPage, - updateFolders, - modelType: 'lora', - createCardFunction: createLoraCard, - endpoint: '/api/loras' - }); + const pageState = getCurrentPageState(); + + // Check if virtual scroller is available + if (state.virtualScroller) { + try { + // Start loading state + pageState.isLoading = true; + document.body.classList.add('loading'); + + // Reset to first page if requested + if (resetPage) { + pageState.currentPage = 1; + } + + // Fetch the first page of data + const result = await fetchLorasPage(pageState.currentPage, pageState.pageSize || 50); + + // Update virtual scroller with the new data + state.virtualScroller.refreshWithData( + result.items, + result.totalItems, + result.hasMore + ); + + // Update state + pageState.hasMore = result.hasMore; + pageState.currentPage = 2; // Next page to load would be 2 + + // Update folders if needed + if (updateFolders && result.folders) { + // Import function dynamically to avoid circular dependencies + const { updateFolderTags } = await import('./baseModelApi.js'); + updateFolderTags(result.folders); + } + + return result; + } catch (error) { + console.error('Error loading loras:', error); + showToast(`Failed to load loras: ${error.message}`, 'error'); + } finally { + pageState.isLoading = false; + document.body.classList.remove('loading'); + } + } else { + // Fall back to the original implementation if virtual scroller isn't available + return loadMoreModels({ + resetPage, + updateFolders, + modelType: 'lora', + createCardFunction: createLoraCard, + endpoint: '/api/loras' + }); + } } /** @@ -87,21 +141,69 @@ export async function replacePreview(filePath) { } export function appendLoraCards(loras) { - const grid = document.getElementById('loraGrid'); - const sentinel = document.getElementById('scroll-sentinel'); - - loras.forEach(lora => { - const card = createLoraCard(lora); - grid.appendChild(card); - }); + // This function is no longer needed with virtual scrolling + // but kept for compatibility + if (state.virtualScroller) { + console.warn('appendLoraCards is deprecated when using virtual scrolling'); + } else { + const grid = document.getElementById('loraGrid'); + + loras.forEach(lora => { + const card = createLoraCard(lora); + grid.appendChild(card); + }); + } } export async function resetAndReload(updateFolders = false) { - return baseResetAndReload({ - updateFolders, - modelType: 'lora', - loadMoreFunction: loadMoreLoras - }); + const pageState = getCurrentPageState(); + + // Check if virtual scroller is available + if (state.virtualScroller) { + try { + pageState.isLoading = true; + document.body.classList.add('loading'); + + // Reset page counter + pageState.currentPage = 1; + + // Fetch the first page + const result = await fetchLorasPage(1, pageState.pageSize || 50); + + // Update the virtual scroller + state.virtualScroller.refreshWithData( + result.items, + result.totalItems, + result.hasMore + ); + + // Update state + pageState.hasMore = result.hasMore; + pageState.currentPage = 2; // Next page will be 2 + + // Update folders if needed + if (updateFolders && result.folders) { + // Import function dynamically to avoid circular dependencies + const { updateFolderTags } = await import('./baseModelApi.js'); + updateFolderTags(result.folders); + } + + return result; + } catch (error) { + console.error('Error reloading loras:', error); + showToast(`Failed to reload loras: ${error.message}`, 'error'); + } finally { + pageState.isLoading = false; + document.body.classList.remove('loading'); + } + } else { + // Fall back to original implementation + return baseResetAndReload({ + updateFolders, + modelType: 'lora', + loadMoreFunction: loadMoreLoras + }); + } } export async function refreshLoras() { diff --git a/static/js/components/LoraCard.js b/static/js/components/LoraCard.js index c2aaa6b1..be53ba41 100644 --- a/static/js/components/LoraCard.js +++ b/static/js/components/LoraCard.js @@ -328,7 +328,7 @@ export function updateCardsForBulkMode(isBulkMode) { document.body.classList.toggle('bulk-mode', isBulkMode); - // Get all lora cards + // Get all lora cards - this can now be from the DOM or through the virtual scroller const loraCards = document.querySelectorAll('.lora-card'); loraCards.forEach(card => { @@ -350,6 +350,11 @@ export function updateCardsForBulkMode(isBulkMode) { } }); + // If using virtual scroller, we need to rerender after toggling bulk mode + if (state.virtualScroller && typeof state.virtualScroller.scheduleRender === 'function') { + state.virtualScroller.scheduleRender(); + } + // Apply selection state to cards if entering bulk mode if (isBulkMode) { bulkManager.applySelectionState(); diff --git a/static/js/components/controls/PageControls.js b/static/js/components/controls/PageControls.js index caf101d5..9569a639 100644 --- a/static/js/components/controls/PageControls.js +++ b/static/js/components/controls/PageControls.js @@ -37,7 +37,7 @@ export class PageControls { */ initializeState() { // Set default values - this.pageState.pageSize = 20; + this.pageState.pageSize = 100; this.pageState.isLoading = false; this.pageState.hasMore = true;