Enhance DuplicatesManager and VirtualScroller to manage virtual scrolling state and improve rendering logic

This commit is contained in:
Will Miao
2025-05-12 21:31:03 +08:00
parent af8f5ba04e
commit c966dbbbbc
4 changed files with 74 additions and 14 deletions

View File

@@ -1,7 +1,7 @@
// Duplicates Manager Component
import { showToast } from '../utils/uiHelpers.js';
import { RecipeCard } from './RecipeCard.js';
import { getCurrentPageState } from '../state/index.js';
import { state, getCurrentPageState } from '../state/index.js';
import { initializeInfiniteScroll } from '../utils/infiniteScroll.js';
export class DuplicatesManager {
@@ -61,10 +61,9 @@ export class DuplicatesManager {
banner.style.display = 'block';
}
// Disable infinite scroll
if (this.recipeManager.observer) {
this.recipeManager.observer.disconnect();
this.recipeManager.observer = null;
// Disable virtual scrolling if active
if (state.virtualScroller) {
state.virtualScroller.disable();
}
// Add duplicate-mode class to the body
@@ -94,13 +93,21 @@ export class DuplicatesManager {
// Remove duplicate-mode class from the body
document.body.classList.remove('duplicate-mode');
// Reload normal recipes view
this.recipeManager.loadRecipes();
// Clear the recipe grid first
const recipeGrid = document.getElementById('recipeGrid');
if (recipeGrid) {
recipeGrid.innerHTML = '';
}
// Reinitialize infinite scroll
setTimeout(() => {
initializeInfiniteScroll('recipes');
}, 500);
// Re-enable virtual scrolling
if (state.virtualScroller) {
state.virtualScroller.enable();
} else {
// If virtual scroller doesn't exist, reinitialize it
setTimeout(() => {
initializeInfiniteScroll('recipes');
}, 100);
}
}
renderDuplicateGroups() {

View File

@@ -221,8 +221,18 @@ class RecipeManager {
}
exitDuplicateMode() {
// Clear the grid first to prevent showing old content temporarily
const recipeGrid = document.getElementById('recipeGrid');
if (recipeGrid) {
recipeGrid.innerHTML = '';
}
this.duplicatesManager.exitDuplicateMode();
initializeInfiniteScroll('recipes');
// Use a small delay before initializing to ensure DOM is ready
setTimeout(() => {
initializeInfiniteScroll('recipes');
}, 100);
}
}

View File

@@ -317,8 +317,9 @@ export class VirtualScroller {
return { start: firstIndex, end: lastIndex };
}
// Update the scheduleRender method to check for disabled state
scheduleRender() {
if (this.renderScheduled) return;
if (this.disabled || this.renderScheduled) return;
this.renderScheduled = true;
requestAnimationFrame(() => {
@@ -327,8 +328,9 @@ export class VirtualScroller {
});
}
// Update the renderItems method to check for disabled state
renderItems() {
if (this.items.length === 0 || this.columnsCount === 0) return;
if (this.disabled || this.items.length === 0 || this.columnsCount === 0) return;
const { start, end } = this.getVisibleRange();
@@ -672,4 +674,44 @@ export class VirtualScroller {
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
// Add disable method to stop rendering and events
disable() {
// Detach scroll event listener
this.scrollContainer.removeEventListener('scroll', this.scrollHandler);
// Clear all rendered items from the DOM
this.clearRenderedItems();
// Hide the spacer element
if (this.spacerElement) {
this.spacerElement.style.display = 'none';
}
// Flag as disabled
this.disabled = true;
console.log('Virtual scroller disabled');
}
// Add enable method to resume rendering and events
enable() {
if (!this.disabled) return;
// Reattach scroll event listener
this.scrollContainer.addEventListener('scroll', this.scrollHandler);
// Show the spacer element
if (this.spacerElement) {
this.spacerElement.style.display = 'block';
}
// Flag as enabled
this.disabled = false;
// Re-render items
this.scheduleRender();
console.log('Virtual scroller enabled');
}
}

View File

@@ -58,6 +58,7 @@ export async function initializeInfiniteScroll(pageType = 'loras') {
// Skip initializing if in duplicates mode (for recipes page)
if (pageType === 'recipes' && pageState.duplicatesMode) {
console.log('Skipping virtual scroll initialization - duplicates mode is active');
return;
}