From 590a3fd03732346891bc3a45ae97b031ee5720ad Mon Sep 17 00:00:00 2001 From: HighImKevin Date: Fri, 25 Sep 2026 14:52:44 -0400 Subject: [PATCH] Further prevent rendering of duplicate progressive sections --- scripts/cardBuilder.js | 9 +++ scripts/homeScreen3.js | 135 ++++++++++++++++++++++------------------- 2 files changed, 80 insertions(+), 64 deletions(-) diff --git a/scripts/cardBuilder.js b/scripts/cardBuilder.js index d7141c7..de496b0 100644 --- a/scripts/cardBuilder.js +++ b/scripts/cardBuilder.js @@ -2122,6 +2122,15 @@ continue; } + // Skip if this section id is already in the container (overlapping home renders) + const sectionIdAttr = (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') + ? CSS.escape(String(sectionConfig.id)) + : String(sectionConfig.id).replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + if (container.querySelector(`[data-section-id="${sectionIdAttr}"]`)) { + console.log(`[KefinTweaks CardBuilder] Section ${sectionConfig.id} already exists in the container, skipping...`); + continue; + } + // Handle Random card format - pick one format for entire section let finalCardFormat = sectionConfig.cardFormat; if (finalCardFormat === 'random' || finalCardFormat === 'Random') { diff --git a/scripts/homeScreen3.js b/scripts/homeScreen3.js index c9e7791..32a43ef 100644 --- a/scripts/homeScreen3.js +++ b/scripts/homeScreen3.js @@ -1117,77 +1117,84 @@ return; } - // Check if children with [data-section-id] are present - const children = container.children; - const hasSections = Array.from(children).some(child => child.dataset && child.dataset.sectionId); - if (hasSections) { - LOG('Sections already rendered, skipping'); + if (state.isRenderingHome) { + LOG('Home render already in progress, skipping'); return; } - container.dataset.sectionsRendered = 'true'; - applyActiveHomeCategory(homeChromeActiveCategory || 'none'); - syncHomeScreenChromeVisibility(); - - const sectionsToRender = []; - - if (useCache && sectionCache.renderedSections.length > 0) { - LOG('Re-rendering home sections from cache'); - sectionsToRender.push(...sectionCache.renderedSections); - } else { - const sortedSections = [...sections].sort((a, b) => { - const orderA = (a.order !== undefined && a.order !== null) ? a.order : 99; - const orderB = (b.order !== undefined && b.order !== null) ? b.order : 99; - return orderA - orderB; - }); - - const sectionPromises = []; - - for (const sectionConfig of sortedSections) { - if (sectionConfig.enabled === false) { - LOG(`Skipping disabled section: ${sectionConfig.id}`); - continue; - } - - if (sectionConfig.startDate && sectionConfig.endDate) { - if (!isInSeasonalPeriod(sectionConfig.startDate, sectionConfig.endDate)) { - LOG(`Skipping seasonal section (out of date): ${sectionConfig.id}`); - continue; - } - } - - const existingSection = container.querySelector(`[data-section-id="${sectionConfig.id}"]`); - - if (existingSection) { - LOG(`Section already rendered: ${sectionConfig.id}`); - continue; - } - - sectionPromises.push(loadSectionForRendering(sectionConfig)); + state.isRenderingHome = true; + try { + // Check if children with [data-section-id] are present + const children = container.children; + const hasSections = Array.from(children).some(child => child.dataset && child.dataset.sectionId); + if (hasSections) { + LOG('Sections already rendered, skipping'); + return; } - // Resolve all section promises - let sectionResults = await Promise.all(sectionPromises); - sectionResults = sectionResults.filter(result => result !== null); - sectionsToRender.push(...sectionResults); + container.dataset.sectionsRendered = 'true'; + applyActiveHomeCategory(homeChromeActiveCategory || 'none'); + syncHomeScreenChromeVisibility(); - // Cache the rendered sections for potential re-render after Jellyfin overwrites the container - sectionCache.renderedSections = [...sectionsToRender]; - } + const sectionsToRender = []; - const homeConfig = await window.KefinHomeScreen.getConfig(); - const showStaleDataBeforeRefresh = homeConfig?.HOME_SETTINGS?.showStaleDataBeforeRefresh === true; + if (useCache && sectionCache.renderedSections.length > 0) { + LOG('Re-rendering home sections from cache'); + sectionsToRender.push(...sectionCache.renderedSections); + } else { + const sortedSections = [...sections].sort((a, b) => { + const orderA = (a.order !== undefined && a.order !== null) ? a.order : 99; + const orderB = (b.order !== undefined && b.order !== null) ? b.order : 99; + return orderA - orderB; + }); - const targetContainer = container; + const sectionPromises = []; - const kefinSections = Array.from(children).some(child => child.dataset && child.dataset.sectionId); - if (kefinSections) { - LOG('Sections already rendered, skipping'); - return; - } + for (const sectionConfig of sortedSections) { + if (sectionConfig.enabled === false) { + LOG(`Skipping disabled section: ${sectionConfig.id}`); + continue; + } - if (!state.isRenderingHome && !kefinSections) { - state.isRenderingHome = true; + if (sectionConfig.startDate && sectionConfig.endDate) { + if (!isInSeasonalPeriod(sectionConfig.startDate, sectionConfig.endDate)) { + LOG(`Skipping seasonal section (out of date): ${sectionConfig.id}`); + continue; + } + } + + const sectionIdAttr = (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') + ? CSS.escape(String(sectionConfig.id)) + : String(sectionConfig.id).replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + const existingSection = container.querySelector(`[data-section-id="${sectionIdAttr}"]`); + + if (existingSection) { + LOG(`Section already rendered: ${sectionConfig.id}`); + continue; + } + + sectionPromises.push(loadSectionForRendering(sectionConfig)); + } + + // Resolve all section promises + let sectionResults = await Promise.all(sectionPromises); + sectionResults = sectionResults.filter(result => result !== null); + sectionsToRender.push(...sectionResults); + + // Cache the rendered sections for potential re-render after Jellyfin overwrites the container + sectionCache.renderedSections = [...sectionsToRender]; + } + + const homeConfig = await window.KefinHomeScreen.getConfig(); + const showStaleDataBeforeRefresh = homeConfig?.HOME_SETTINGS?.showStaleDataBeforeRefresh === true; + + const targetContainer = container; + + const kefinSections = Array.from(children).some(child => child.dataset && child.dataset.sectionId); + if (kefinSections) { + LOG('Sections already rendered, skipping'); + return; + } await window.cardBuilder.renderProgressiveSections(targetContainer, sectionsToRender, { waitForContainerClass: 'homeSectionsContainer', @@ -1195,8 +1202,6 @@ showStaleDataBeforeRefresh }); - state.isRenderingHome = false; - // If MediaBar plugin is in use, call LayoutSync.update() to update the layout if (typeof LayoutSync !== 'undefined' && LayoutSync && typeof LayoutSync.update === 'function') { LayoutSync.update(); @@ -1209,11 +1214,13 @@ document.dispatchEvent(new CustomEvent('kefinTweaksHomePainted')); } catch (_) { /* ignore */ } } - + // Check if target container is homeSectionsContainer if (!targetContainer.classList.contains('homeSectionsContainer')) { targetContainer.dataset.sectionsPrerendered = 'true'; } + } finally { + state.isRenderingHome = false; } }