Add the ability to select a Render Mode for Home Screen sections: Normal, Spotlight, Random

This commit is contained in:
HighImKevin
2025-12-06 21:06:23 -05:00
parent e9995ee8f7
commit fedd919501
2 changed files with 46 additions and 70 deletions
+14 -5
View File
@@ -1180,6 +1180,7 @@
const cardFormat = section.cardFormat || 'Poster';
const order = section.order || 100;
const spotlightEnabled = section.spotlight === true;
const renderMode = section.renderMode || (spotlightEnabled ? 'Spotlight' : 'Normal');
const discoveryEnabled = section.discoveryEnabled === true;
const searchTerm = section.searchTerm || '';
const includeItemTypes = Array.isArray(section.includeItemTypes) ? section.includeItemTypes : (section.includeItemTypes ? section.includeItemTypes.split(',').map(s => s.trim()).filter(Boolean) : (type === 'Parent' ? [] : ['Movie']));
@@ -1269,15 +1270,19 @@
if (useImprovedLayout) {
// Custom sections: Row 1 (checkboxes + type), Row 2 (source), Row 3+ (remaining fields in 3 columns)
sectionContent = `
<!-- Row 1: Enabled, Spotlight, Discovery, Type -->
<!-- Row 1: Enabled, Render Mode, Discovery, Type -->
<div class="listItem" style="display: grid; grid-template-columns: auto auto auto 1fr; gap: 1em; align-items: end; margin: 0.75em 0; border: 1px solid rgba(255,255,255,0.1); border-radius: 4px; padding: 0.75em;">
<div>
<div class="listItemBodyText secondary" style="font-size: 0.85em; margin-bottom: 0.25em;">Enabled</div>
${buildJellyfinCheckbox(`${prefix}_section_enabled_${sectionIndex}`, enabled, '', { 'data-section-index': sectionIndex, 'data-prefix': prefix, 'class': `${prefix}_section_enabled` })}
</div>
<div>
<div class="listItemBodyText secondary" style="font-size: 0.85em; margin-bottom: 0.25em;">Spotlight</div>
${buildJellyfinCheckbox(spotlightCheckboxId, spotlightEnabled, 'Enable Spotlight', { 'data-section-index': sectionIndex, 'data-prefix': prefix, 'class': `${prefix}_section_spotlight` })}
<div class="listItemBodyText secondary" style="font-size: 0.85em; margin-bottom: 0.25em;">Render Mode</div>
<select class="${prefix}_section_renderMode fld emby-select-withcolor emby-select" data-section-index="${sectionIndex}" data-prefix="${prefix}" style="width: 100%;">
<option value="Normal" ${renderMode === 'Normal' ? 'selected' : ''}>Normal</option>
<option value="Spotlight" ${renderMode === 'Spotlight' ? 'selected' : ''}>Spotlight</option>
<option value="Random" ${renderMode === 'Random' ? 'selected' : ''}>Random</option>
</select>
</div>
<div>
<div class="listItemBodyText secondary" style="font-size: 0.85em; margin-bottom: 0.25em;">Discovery</div>
@@ -4760,9 +4765,12 @@ window.KefinTweaksConfig = ${JSON.stringify(config, null, 2)};`;
const sortOrderDirection = sectionItem.querySelector(`#${prefix}_section_${sanitizedIndex}_sortOrderDirection`)?.value || 'Ascending';
const cardFormat = sectionItem.querySelector(`#${prefix}_section_${sanitizedIndex}_cardFormat`)?.value || 'Poster';
const order = parseInt(sectionItem.querySelector(`#${prefix}_section_${sanitizedIndex}_order`)?.value || '100', 10);
const spotlightCheckbox = sectionItem.querySelector(`#${prefix}_section_${sanitizedIndex}_spotlight`) || sectionItem.querySelector(`.${prefix}_section_spotlight[data-section-index="${sectionIndex}"]`);
const renderModeSelect = sectionItem.querySelector(`.${prefix}_section_renderMode[data-section-index="${sectionIndex}"]`);
const renderMode = renderModeSelect ? renderModeSelect.value : 'Normal';
const spotlight = renderMode === 'Spotlight'; // Legacy compatibility
const discoveryCheckbox = sectionItem.querySelector(`#${prefix}_section_${sanitizedIndex}_discovery`) || sectionItem.querySelector(`.${prefix}_section_discovery[data-section-index="${sectionIndex}"]`);
const spotlight = spotlightCheckbox?.checked === true;
const discoveryEnabled = discoveryCheckbox?.checked === true;
const searchTerm = sectionItem.querySelector(`#${prefix}_section_${sanitizedIndex}_searchTerm`)?.value?.trim() || '';
@@ -4809,6 +4817,7 @@ window.KefinTweaksConfig = ${JSON.stringify(config, null, 2)};`;
sortOrderDirection: sortOrderDirection,
cardFormat: cardFormat,
order: order,
renderMode: renderMode,
spotlight: spotlight,
discoveryEnabled: discoveryEnabled,
searchTerm: searchTerm,
+32 -65
View File
@@ -1326,68 +1326,20 @@
*/
async function renderCustomSection(section, container) {
try {
// Support new structure (type + source) and legacy structure (sourceId)
const type = section.type;
const source = section.source || section.sourceId || section.id;
// Support legacy structure (sourceId/id without source)
// Create a copy to avoid mutating the original config object
const sectionConfig = { ...section };
if (!source) {
ERR(`No source provided for section ${section.name}`);
return false;
/* if (!sectionConfig.source && (sectionConfig.sourceId || sectionConfig.id)) {
sectionConfig.source = sectionConfig.sourceId || sectionConfig.id;
} */
// Ensure ID exists for renderSection
if (!sectionConfig.id) {
sectionConfig.id = sectionConfig.source;
}
const sortOrder = section.sortOrder ?? defaultSortOrder;
const sortOrderDirection = section.sortOrderDirection ?? 'Ascending';
const cardFormat = section.cardFormat ?? defaultCardFormat;
const order = section.order ?? 100;
const useSpotlight = section.spotlight === true;
let viewMoreUrl = null;
switch (type) {
case 'Genre':
viewMoreUrl = `#/list.html?genreId=${source}&serverId=${ApiClient.serverId()}`;
break;
case 'Studio':
viewMoreUrl = `#/list.html?studioId=${source}&serverId=${ApiClient.serverId()}`;
break;
case 'Playlist':
case 'BoxSet':
viewMoreUrl = `#/details?id=${source}&serverId=${ApiClient.serverId()}`;
break;
case 'Parent':
viewMoreUrl = `#/list.html?parentId=${source}&serverId=${ApiClient.serverId()}`;
break;
default:
viewMoreUrl = null;
break;
}
// If new structure with type, use renderSection helper
if (useSpotlight && window.cardBuilder.renderSpotlightSection) {
const items = await loadItemsForSectionConfig(section);
const spotlightContainer = window.cardBuilder.renderSpotlightSection(
items,
section.name ?? 'Spotlight',
{
autoPlay: spotlightAutoPlay,
interval: spotlightInterval,
showDots: spotlightShowDots,
showNavButtons: spotlightShowNavButtons,
showClearArt: spotlightShowClearArt,
viewMoreUrl: viewMoreUrl
}
);
spotlightContainer.setAttribute('data-custom-section-id', section.id || source);
spotlightContainer.setAttribute('data-custom-section-name', section.name);
spotlightContainer.setAttribute('data-custom-section-type', type);
spotlightContainer.style.order = order;
container.appendChild(spotlightContainer);
return true;
}
return await renderSection(section, container, 'custom');
return await renderSection(sectionConfig, container, 'custom');
} catch (err) {
ERR(`Error rendering section ${section.name}:`, err);
return false;
@@ -5660,21 +5612,33 @@
let cardContainer = null;
if (sectionConfig.spotlight === true) {
// Render Mode Logic
const renderMode = sectionConfig.renderMode || (sectionConfig.spotlight ? 'Spotlight' : 'Normal');
let useSpotlight = renderMode === 'Spotlight';
if (renderMode === 'Random') {
useSpotlight = Math.random() < 0.5;
}
if (useSpotlight) {
if (!window.cardBuilder || !window.cardBuilder.renderSpotlightSection) {
WARN("cardBuilder.renderSpotlightSection not available");
return false;
}
// Use global spotlight config if available
const homeScreenConfig = window.KefinTweaksConfig?.homeScreen || {};
const spotlightConfig = homeScreenConfig.spotlight || {};
cardContainer = window.cardBuilder.renderSpotlightSection(
limited,
sectionConfig.name,
{
autoPlay: true,
interval: 5000,
showDots: true,
showNavButtons: true,
showClearArt: true,
autoPlay: spotlightConfig.autoPlay ?? true,
interval: spotlightConfig.interval ?? 5000,
showDots: spotlightConfig.showDots ?? true,
showNavButtons: spotlightConfig.showNavButtons ?? true,
showClearArt: spotlightConfig.showClearArt ?? true,
viewMoreUrl: viewMoreUrl
}
);
@@ -5697,6 +5661,9 @@
cardContainer.setAttribute('data-custom-section-id', sectionId);
cardContainer.setAttribute('data-custom-section-name', sectionConfig.name);
if (sectionConfig.type) {
cardContainer.setAttribute('data-custom-section-type', sectionConfig.type);
}
cardContainer.style.order = order;
container.appendChild(cardContainer);