mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 07:05:43 -03:00
checkpoint
This commit is contained in:
@@ -1,12 +1,63 @@
|
||||
import { state, getCurrentPageState } from '../state/index.js';
|
||||
import { loadMoreLoras } from '../api/loraApi.js';
|
||||
import { loadMoreCheckpoints } from '../api/checkpointApi.js';
|
||||
import { debounce } from './debounce.js';
|
||||
import { VirtualScroller } from './VirtualScroller.js';
|
||||
import { createLoraCard } from '../components/LoraCard.js';
|
||||
import { fetchLorasPage } from '../api/loraApi.js';
|
||||
import { showToast } from './uiHelpers.js';
|
||||
|
||||
export function initializeInfiniteScroll(pageType = 'loras') {
|
||||
// Clean up any existing observer
|
||||
if (state.observer) {
|
||||
state.observer.disconnect();
|
||||
// Function to dynamically import the appropriate card creator based on page type
|
||||
async function getCardCreator(pageType) {
|
||||
if (pageType === 'loras') {
|
||||
return createLoraCard;
|
||||
} else if (pageType === 'recipes') {
|
||||
try {
|
||||
const { createRecipeCard } = await import('../components/RecipeCard.js');
|
||||
return createRecipeCard;
|
||||
} catch (err) {
|
||||
console.error('Failed to load recipe card creator:', err);
|
||||
return null;
|
||||
}
|
||||
} else if (pageType === 'checkpoints') {
|
||||
try {
|
||||
const { createCheckpointCard } = await import('../components/CheckpointCard.js');
|
||||
return createCheckpointCard;
|
||||
} catch (err) {
|
||||
console.error('Failed to load checkpoint card creator:', err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Function to get the appropriate data fetcher based on page type
|
||||
async function getDataFetcher(pageType) {
|
||||
if (pageType === 'loras') {
|
||||
return fetchLorasPage;
|
||||
} else if (pageType === 'recipes') {
|
||||
try {
|
||||
const { fetchRecipesPage } = await import('../api/recipeApi.js');
|
||||
return fetchRecipesPage;
|
||||
} catch (err) {
|
||||
console.error('Failed to load recipe data fetcher:', err);
|
||||
return null;
|
||||
}
|
||||
} else if (pageType === 'checkpoints') {
|
||||
try {
|
||||
const { fetchCheckpointsPage } = await import('../api/checkpointApi.js');
|
||||
return fetchCheckpointsPage;
|
||||
} catch (err) {
|
||||
console.error('Failed to load checkpoint data fetcher:', err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function initializeInfiniteScroll(pageType = 'loras') {
|
||||
// Clean up any existing virtual scroller
|
||||
if (state.virtualScroller) {
|
||||
state.virtualScroller.dispose();
|
||||
state.virtualScroller = null;
|
||||
}
|
||||
|
||||
// Set the current page type
|
||||
@@ -20,106 +71,83 @@ export function initializeInfiniteScroll(pageType = 'loras') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the load more function and grid ID based on page type
|
||||
let loadMoreFunction;
|
||||
// Use virtual scrolling for all page types
|
||||
await initializeVirtualScroll(pageType);
|
||||
}
|
||||
|
||||
async function initializeVirtualScroll(pageType) {
|
||||
// Determine the grid ID based on page type
|
||||
let gridId;
|
||||
|
||||
switch (pageType) {
|
||||
case 'recipes':
|
||||
loadMoreFunction = () => {
|
||||
if (!pageState.isLoading && pageState.hasMore) {
|
||||
window.recipeManager.loadRecipes(false); // false to not reset pagination
|
||||
}
|
||||
};
|
||||
gridId = 'recipeGrid';
|
||||
break;
|
||||
case 'checkpoints':
|
||||
loadMoreFunction = () => {
|
||||
if (!pageState.isLoading && pageState.hasMore) {
|
||||
loadMoreCheckpoints(false); // false to not reset
|
||||
}
|
||||
};
|
||||
gridId = 'checkpointGrid';
|
||||
break;
|
||||
case 'loras':
|
||||
default:
|
||||
loadMoreFunction = () => {
|
||||
if (!pageState.isLoading && pageState.hasMore) {
|
||||
loadMoreLoras(false); // false to not reset
|
||||
}
|
||||
};
|
||||
gridId = 'loraGrid';
|
||||
break;
|
||||
}
|
||||
|
||||
const debouncedLoadMore = debounce(loadMoreFunction, 100);
|
||||
|
||||
const grid = document.getElementById(gridId);
|
||||
|
||||
if (!grid) {
|
||||
console.warn(`Grid with ID "${gridId}" not found for infinite scroll`);
|
||||
console.warn(`Grid with ID "${gridId}" not found for virtual scroll`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove any existing sentinel
|
||||
const existingSentinel = document.getElementById('scroll-sentinel');
|
||||
if (existingSentinel) {
|
||||
existingSentinel.remove();
|
||||
const pageContent = document.querySelector('.page-content');
|
||||
|
||||
if (!pageContent) {
|
||||
console.warn('Page content element not found for virtual scroll');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a sentinel element after the grid (not inside it)
|
||||
const sentinel = document.createElement('div');
|
||||
sentinel.id = 'scroll-sentinel';
|
||||
sentinel.style.width = '100%';
|
||||
sentinel.style.height = '20px';
|
||||
sentinel.style.visibility = 'hidden'; // Make it invisible but still affect layout
|
||||
|
||||
// Insert after grid instead of inside
|
||||
grid.parentNode.insertBefore(sentinel, grid.nextSibling);
|
||||
|
||||
// Create observer with appropriate settings, slightly different for checkpoints page
|
||||
const observerOptions = {
|
||||
threshold: 0.1,
|
||||
rootMargin: pageType === 'checkpoints' ? '0px 0px 200px 0px' : '0px 0px 100px 0px'
|
||||
};
|
||||
|
||||
// Initialize the observer
|
||||
state.observer = new IntersectionObserver((entries) => {
|
||||
const target = entries[0];
|
||||
if (target.isIntersecting && !pageState.isLoading && pageState.hasMore) {
|
||||
debouncedLoadMore();
|
||||
try {
|
||||
// Get the card creator and data fetcher for this page type
|
||||
const createCardFn = await getCardCreator(pageType);
|
||||
const fetchDataFn = await getDataFetcher(pageType);
|
||||
|
||||
if (!createCardFn || !fetchDataFn) {
|
||||
throw new Error(`Required components not available for ${pageType} page`);
|
||||
}
|
||||
}, observerOptions);
|
||||
|
||||
// Start observing
|
||||
state.observer.observe(sentinel);
|
||||
|
||||
// Clean up any existing scroll event listener
|
||||
if (state.scrollHandler) {
|
||||
window.removeEventListener('scroll', state.scrollHandler);
|
||||
state.scrollHandler = null;
|
||||
|
||||
// Initialize the virtual scroller
|
||||
state.virtualScroller = new VirtualScroller({
|
||||
gridElement: grid,
|
||||
containerElement: pageContent,
|
||||
createItemFn: createCardFn,
|
||||
fetchItemsFn: fetchDataFn,
|
||||
pageSize: 100
|
||||
});
|
||||
|
||||
// Initialize the virtual scroller
|
||||
await state.virtualScroller.initialize();
|
||||
|
||||
// Add grid class for CSS styling
|
||||
grid.classList.add('virtual-scroll');
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error initializing virtual scroller for ${pageType}:`, error);
|
||||
showToast(`Failed to initialize ${pageType} page. Please reload.`, 'error');
|
||||
|
||||
// Fallback: show a message in the grid
|
||||
grid.innerHTML = `
|
||||
<div class="placeholder-message">
|
||||
<h3>Failed to initialize ${pageType}</h3>
|
||||
<p>There was an error loading this page. Please try reloading.</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// Add a simple backup scroll handler
|
||||
const handleScroll = debounce(() => {
|
||||
if (pageState.isLoading || !pageState.hasMore) return;
|
||||
|
||||
const sentinel = document.getElementById('scroll-sentinel');
|
||||
if (!sentinel) return;
|
||||
|
||||
const rect = sentinel.getBoundingClientRect();
|
||||
const windowHeight = window.innerHeight;
|
||||
|
||||
if (rect.top < windowHeight + 200) {
|
||||
debouncedLoadMore();
|
||||
}
|
||||
}, 200);
|
||||
|
||||
state.scrollHandler = handleScroll;
|
||||
window.addEventListener('scroll', state.scrollHandler);
|
||||
|
||||
// Clear any existing interval
|
||||
if (state.scrollCheckInterval) {
|
||||
clearInterval(state.scrollCheckInterval);
|
||||
state.scrollCheckInterval = null;
|
||||
}
|
||||
|
||||
// Export a method to refresh the virtual scroller when filters change
|
||||
export function refreshVirtualScroll() {
|
||||
if (state.virtualScroller) {
|
||||
state.virtualScroller.reset();
|
||||
state.virtualScroller.initialize();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user