Fix problem caused by using legacy sortOrder/sortOrderDirection for discovery sections

This commit is contained in:
HighImKevin committed 2026-10-20 16:07:03 -04:00
1 parent a93a82decc
commit 0394aced14
5 files changed
+253 -74

No files matched your search

+74 -3
View File
@@ -167,7 +167,7 @@
'itemsLayout', 'useGaplessCards', 'sectionCssClass', 'hideName'
];
const RESTORE_ADVANCED_KEYS = [
'ttl', 'sortBy', 'sortOrder', 'sortOrderDirection',
'ttl', 'sortBy', 'sortOrder',
'minimumItems', 'itemLimit', 'flattenSeries', 'limitBeforeSort', 'hideWatched'
];
const TTL_UNIT_OPTIONS = [
@@ -1444,6 +1444,63 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
return true; // flag always newly stamped → needs save
}
// TEMPORARY: one-time overwrite of saved Kefin discovery sort fields from the new
// sortBy + sortOrder defaults. Remove in a future release once existing installs
// have picked up the patch (see discoverySortOrdersPatched).
// TODO(remove): patchDiscoverySortOrdersOnce + call site + discoverySortPatch log field
function patchDiscoverySortOrdersOnce(config) {
if (!window.KefinTweaksConfig) window.KefinTweaksConfig = {};
if (window.KefinTweaksConfig.discoverySortOrdersPatched === true) return false;
if (!Array.isArray(window.KefinHomeConfig2?.DISCOVERY_SECTION_GROUPS)) return false;
const canonicalMap = buildCanonicalSectionMapForGroups('DISCOVERY_SECTION_GROUPS');
const isDirection = (value) => value === 'Ascending' || value === 'Descending';
const topRatedQueryResetIds = new Set(['spotlightGenre', 'spotlightGenreSeries', 'spotlightNetwork']);
const applySortPair = (target, canonical, fieldKey, directionKey) => {
if (!target || !canonical) return;
if (canonical[fieldKey]) target[fieldKey] = canonical[fieldKey];
else delete target[fieldKey];
if (isDirection(canonical[directionKey])) target[directionKey] = canonical[directionKey];
else delete target[directionKey];
};
for (const group of config.DISCOVERY_SECTION_GROUPS || []) {
for (const section of group.sections || []) {
if (!section?.id) continue;
const canonical = canonicalMap.get(section.id);
if (!canonical) continue;
applySortPair(section, canonical, 'sortBy', 'sortOrder');
delete section.sortOrderDirection;
const savedQueries = section.queries || [];
const canonicalQueries = canonical.queries || [];
const count = Math.min(savedQueries.length, canonicalQueries.length);
const replaceQueryOptions = topRatedQueryResetIds.has(section.id);
for (let i = 0; i < count; i++) {
const savedQuery = savedQueries[i];
const canonicalQuery = canonicalQueries[i];
if (!savedQuery || !canonicalQuery) continue;
if (replaceQueryOptions) {
savedQuery.queryOptions = JSON.parse(JSON.stringify(canonicalQuery.queryOptions || {}));
continue;
}
const canonicalOpts = canonicalQuery.queryOptions || {};
if (!savedQuery.queryOptions) {
if (!canonicalOpts.SortBy && !isDirection(canonicalOpts.SortOrder)) continue;
savedQuery.queryOptions = {};
}
applySortPair(savedQuery.queryOptions, canonicalOpts, 'SortBy', 'SortOrder');
}
}
}
window.KefinTweaksConfig.discoverySortOrdersPatched = true;
return true; // flag always newly stamped → needs save
}
async function ensureKefinTweaksDefaultSections() {
try {
if (!window.ApiClient || !window.ApiClient._loggedIn) {
@@ -1477,8 +1534,10 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
const seasonalThemeChanges = syncSeasonalThemesFromDefaults(config);
// TEMPORARY / TODO(remove): one-time liveTv-on-now Limit patch
const liveTvLimitPatch = patchLiveTvOnNowLimitOnce(config);
// TEMPORARY / TODO(remove): one-time discovery sortBy/sortOrder overwrite
const discoverySortPatch = patchDiscoverySortOrdersOnce(config);
if (libraryChanges || addedDefaults || prunedOrphans || defaultSyncChanges || seasonalThemeChanges || liveTvLimitPatch) {
if (libraryChanges || addedDefaults || prunedOrphans || defaultSyncChanges || seasonalThemeChanges || liveTvLimitPatch || discoverySortPatch) {
await saveConfig(config);
LOG('KefinTweaks default home sections synced on startup', {
libraryChanges,
@@ -1486,7 +1545,8 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
prunedOrphans,
defaultSyncChanges,
seasonalThemeChanges,
liveTvLimitPatch
liveTvLimitPatch,
discoverySortPatch
});
}
} catch (error) {
@@ -1919,6 +1979,11 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
...(savedQuery.queryOptions || {}),
...currentQuery.queryOptions
};
['SortBy', 'SortOrder'].forEach((key) => {
if (!Object.prototype.hasOwnProperty.call(currentQuery.queryOptions, key)) {
delete merged.queryOptions[key];
}
});
} else if (savedQuery.queryOptions) {
merged.queryOptions = JSON.parse(JSON.stringify(savedQuery.queryOptions));
}
@@ -1992,6 +2057,12 @@ window.KefinTweaksConfig = ${JSON.stringify(configToBackup, null, 2)};`;
merged[key] = currentSection[key];
}
});
['sortBy', 'sortOrder'].forEach((key) => {
if (!Object.prototype.hasOwnProperty.call(currentSection, key)) {
delete merged[key];
}
});
// Ensure id is preserved from currentSection
if (currentSection.id) {
+19 -2
View File
@@ -628,8 +628,25 @@
found.section.isPlayed = legacySectionConfig.isPlayed;
}
if (legacySectionConfig.minimumItems !== undefined) found.section.minimumItems = legacySectionConfig.minimumItems;
if (legacySectionConfig.sortOrder !== undefined) found.section.sortOrder = legacySectionConfig.sortOrder;
if (legacySectionConfig.sortOrderDirection !== undefined) found.section.sortOrderDirection = legacySectionConfig.sortOrderDirection;
if (legacySectionConfig.sortOrder !== undefined) {
const legacySort = String(legacySectionConfig.sortOrder).trim();
if (legacySort === 'Ascending' || legacySort === 'Descending') {
found.section.sortOrder = legacySort;
} else if (legacySort) {
found.section.sortBy = legacySort;
const existingOrder = found.section.sortOrder == null ? '' : String(found.section.sortOrder).trim();
if (existingOrder !== 'Ascending' && existingOrder !== 'Descending') {
delete found.section.sortOrder;
}
}
}
if (legacySectionConfig.sortOrderDirection !== undefined) {
const legacyDirection = String(legacySectionConfig.sortOrderDirection).trim();
if (legacyDirection === 'Ascending' || legacyDirection === 'Descending') {
found.section.sortOrder = legacyDirection;
}
}
delete found.section.sortOrderDirection;
const isRecentlyWatchedPerson = RECENTLY_WATCHED_PERSON_IDS.has(sectionKey);
if (legacySectionConfig.name !== undefined) {
+112 -40
View File
@@ -452,11 +452,26 @@
.replace(/([A-Z])([A-Z][a-z])/g, '$1 $2');
}
const SORT_BY_NONE = 'None';
function toSortBySelectOptions(sortOrders) {
return (sortOrders || []).map(value => ({
value,
label: humanizeSortOrderLabel(value)
}));
return [
{ value: SORT_BY_NONE, label: 'None' },
...(sortOrders || []).map(value => ({
value,
label: humanizeSortOrderLabel(value)
}))
];
}
function sortBySelectValue(stored) {
const value = stored == null ? '' : String(stored).trim();
return value || SORT_BY_NONE;
}
function isSortByNone(value) {
const by = value == null ? '' : String(value).trim();
return !by || by === SORT_BY_NONE;
}
function getSectionSortOrderDirectionOptions(directions) {
@@ -484,15 +499,63 @@
return allowed.includes(profile);
}
const SECTION_SORT_DIRECTIONS = new Set(['Ascending', 'Descending']);
function isSectionSortDirection(value) {
return SECTION_SORT_DIRECTIONS.has(String(value || '').trim());
}
/**
* Legacy sortOrder stored the field (Random, CommunityRating, …) and
* sortOrderDirection stored Ascending/Descending. Current model is
* sortBy = field, sortOrder = direction only.
*/
function normalizeSectionSortFields(section) {
if (!section || typeof section !== 'object') return section;
const order = section.sortOrder == null ? '' : String(section.sortOrder).trim();
const legacyDirection = section.sortOrderDirection == null ? '' : String(section.sortOrderDirection).trim();
if (order && !isSectionSortDirection(order)) {
if (!section.sortBy) section.sortBy = order;
delete section.sortOrder;
}
if (isSectionSortDirection(legacyDirection)) {
section.sortOrder = legacyDirection;
}
delete section.sortOrderDirection;
return section;
}
function applySectionLevelSort(section, sortBy, sortOrder) {
const by = sortBy == null ? '' : String(sortBy).trim();
const order = sortOrder == null ? '' : String(sortOrder).trim();
delete section.sortOrderDirection;
if (!by || by === 'Default') delete section.sortBy;
else section.sortBy = by;
if (isSortByNone(by)) {
delete section.sortBy;
delete section.sortOrder;
return;
}
if (!order || order === 'Default') delete section.sortOrder;
else section.sortOrder = order;
section.sortBy = by;
if (isSectionSortDirection(order)) section.sortOrder = order;
else delete section.sortOrder;
}
function applyCollectedQuerySort(queryOptions, sortBy, sortOrder) {
if (!queryOptions) return;
const by = sortBy == null ? '' : String(sortBy).trim();
const order = sortOrder == null ? '' : String(sortOrder).trim();
if (isSortByNone(by)) {
delete queryOptions.SortBy;
delete queryOptions.SortOrder;
return;
}
queryOptions.SortBy = by;
if (isSectionSortDirection(order)) queryOptions.SortOrder = order;
else delete queryOptions.SortOrder;
}
function resolvePremiereAgeFields(section) {
@@ -513,19 +576,14 @@
}
}
const sortByEl = dialog.querySelector('#hsae-advanced-sortBy');
if (isProfileFieldActive(root, sortByEl)) {
const sortVal = sortByEl?.value;
delete section.sortBy;
if (sortVal && sortVal !== 'Default') section.sortOrder = sortVal;
else delete section.sortOrder;
}
normalizeSectionSortFields(section);
const sortByEl = dialog.querySelector('#hsae-advanced-sortBy');
const sortDirEl = dialog.querySelector('#hsae-advanced-sortOrder');
if (isProfileFieldActive(root, sortDirEl)) {
const dirVal = sortDirEl?.value;
if (dirVal && dirVal !== 'Default') section.sortOrderDirection = dirVal;
else delete section.sortOrderDirection;
if (isProfileFieldActive(root, sortByEl)) {
applySectionLevelSort(section, sortByEl?.value, sortDirEl?.value);
} else {
delete section.sortOrderDirection;
}
}
@@ -545,10 +603,12 @@
const sortByEl = dialog.querySelector('#hsae-advanced-sortBy');
const sortOrderEl = dialog.querySelector('#hsae-advanced-sortOrder');
normalizeSectionSortFields(section);
if (isProfileFieldActive(root, sortByEl) && !isDiscoverySection(section)) {
if (section.useRandomQuery) {
delete section.sortBy;
delete section.sortOrder;
delete section.sortOrderDirection;
} else {
applySectionLevelSort(section, sortByEl?.value, sortOrderEl?.value);
}
@@ -991,9 +1051,13 @@
const renderMode = section.renderMode || (section.spotlight ? 'Spotlight' : 'Normal');
const ttlMatch = matchTtlPreset(section.ttl);
const groupSelection = resolveGroupSelection(section, context);
const isDiscovery = isDiscoverySection(section);
const sectionSortBy = section.sortBy || (isDiscovery ? section.sortOrder : '') || '';
const sectionSortOrder = isDiscovery ? (section.sortOrderDirection || '') : (section.sortOrder || '');
const normalizedSort = normalizeSectionSortFields({
sortBy: section.sortBy,
sortOrder: section.sortOrder,
sortOrderDirection: section.sortOrderDirection
});
const sectionSortBy = normalizedSort.sortBy || '';
const sectionSortOrder = isSectionSortDirection(normalizedSort.sortOrder) ? normalizedSort.sortOrder : '';
return {
section,
@@ -1540,7 +1604,7 @@
<div class="hsae-field-grid hsae-query-row-sort">
<div class="hsae-query-sort-by" data-hsae-profiles="full normal dateCutoffs">
${buildSelect(`query-${index}-SortBy`, toSortBySelectOptions(SORT_ORDERS), queryOptions.SortBy || '', 'Sort By')}
${buildSelect(`query-${index}-SortBy`, toSortBySelectOptions(SORT_ORDERS), sortBySelectValue(queryOptions.SortBy), 'Sort By')}
</div>
<div class="hsae-query-sort-order" data-hsae-profiles="full normal dateCutoffs">
${buildSelect(`query-${index}-SortOrder`, SORT_ORDER_DIRECTIONS, queryOptions.SortOrder || '', 'Sort Order')}
@@ -2310,7 +2374,7 @@
<div class="hsae-advanced-section-sort hsae-field-grid hsae-field-grid-2 hsae-advanced-sort-row" data-hsae-profiles="full postProcessing normal dateCutoffs">
<div class="hsae-field-with-hint">
${buildSelect('hsae-advanced-sortBy', toSortBySelectOptions(SORT_ORDERS), state.sortBy || '', 'Sort By')}
${buildSelect('hsae-advanced-sortBy', toSortBySelectOptions(SORT_ORDERS), sortBySelectValue(state.sortBy), 'Sort By')}
<div class="listItemBodyText secondary hsae-field-hint">Items will be sorted in this order after they are returned from Jellyfin.</div>
</div>
<div class="hsae-field-with-hint">
@@ -2442,12 +2506,11 @@
}
}
if (isProfileFieldActive(root, sortByEl)) {
const sortBy = sortByEl?.value;
const sortOrder = editor.querySelector(`#query-${queryIndex}-SortOrder`)?.value;
if (sortBy) query.queryOptions.SortBy = sortBy;
else delete query.queryOptions.SortBy;
if (sortOrder) query.queryOptions.SortOrder = sortOrder;
else delete query.queryOptions.SortOrder;
applyCollectedQuerySort(
query.queryOptions,
sortByEl?.value,
editor.querySelector(`#query-${queryIndex}-SortOrder`)?.value
);
}
if (hideWatched) query.queryOptions.IsUnplayed = true;
else if (query.queryOptions) delete query.queryOptions.IsUnplayed;
@@ -2467,10 +2530,11 @@
if (staticItems.length) {
query.queryOptions.Ids = staticItems.map(item => item.id);
}
['SortBy', 'SortOrder'].forEach(key => {
const value = editor.querySelector(`#query-${queryIndex}-${key}`)?.value;
if (value) query.queryOptions[key] = value;
});
applyCollectedQuerySort(
query.queryOptions,
editor.querySelector(`#query-${queryIndex}-SortBy`)?.value,
editor.querySelector(`#query-${queryIndex}-SortOrder`)?.value
);
return query;
}
@@ -2479,10 +2543,11 @@
|| CACHE_SOURCE_OPTIONS[0]?.value;
if (dataSource) query.dataSource = dataSource;
query.queryOptions = {};
['SortBy', 'SortOrder'].forEach(key => {
const value = editor.querySelector(`#query-${queryIndex}-${key}`)?.value;
if (value) query.queryOptions[key] = value;
});
applyCollectedQuerySort(
query.queryOptions,
editor.querySelector(`#query-${queryIndex}-SortBy`)?.value,
editor.querySelector(`#query-${queryIndex}-SortOrder`)?.value
);
const limit = editor.querySelector(`#query-${queryIndex}-Limit`)?.value;
if (limit !== '' && limit != null) {
const limitN = parseInt(limit, 10);
@@ -2550,7 +2615,12 @@
delete query.queryOptions.PlaylistIds;
delete query.queryOptions._parentItemType;
['SortBy', 'SortOrder', 'Filters', 'SearchTerm'].forEach(key => {
applyCollectedQuerySort(
query.queryOptions,
editor.querySelector(`#query-${queryIndex}-SortBy`)?.value,
editor.querySelector(`#query-${queryIndex}-SortOrder`)?.value
);
['Filters', 'SearchTerm'].forEach(key => {
const value = editor.querySelector(`#query-${queryIndex}-${key}`)?.value;
if (value) query.queryOptions[key] = value;
});
@@ -3651,7 +3721,7 @@
'name', 'caption', 'description', 'enabled', 'order', 'cardFormat', 'renderMode', 'ttl',
'queries', 'items', 'externalListUrls', 'spotlightConfig', 'hideName', 'userConfigurable',
'useRandomQuery', 'useMultiQueryPicker', 'multiQueryPickerLabel', 'useQueryNamesForSection',
'sortBy', 'sortOrder', 'sortOrderDirection', 'itemLimit', 'minimumItems', 'flattenSeries',
'sortBy', 'sortOrder', 'itemLimit', 'minimumItems', 'flattenSeries',
'limitBeforeSort', 'sectionCssClass', 'borderStyle', 'borderColor', 'cardTitleColor',
'itemsLayout', 'useGaplessCards', 'cardTitleVisibility', 'useParentCard', 'cardTitlePosition',
'cardTitleCapitalization', 'cardTitleFontFamily', 'cardTitleFontSize', 'startDate', 'endDate',
@@ -3959,6 +4029,8 @@
function diffSectionAgainstDefault(current, canonical) {
const diffs = [];
if (!current || !canonical) return diffs;
current = normalizeSectionSortFields({ ...current });
canonical = normalizeSectionSortFields({ ...canonical });
for (const key of HSAE_SECTION_DIFF_KEYS) {
const hasCurrent = Object.prototype.hasOwnProperty.call(current, key);
const hasCanonical = Object.prototype.hasOwnProperty.call(canonical, key);
+27 -27
View File
@@ -1814,7 +1814,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -1881,7 +1881,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -1912,7 +1912,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -1943,7 +1943,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -1989,7 +1989,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2028,7 +2028,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2067,7 +2067,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2110,7 +2110,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
{
@@ -2144,7 +2144,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2178,7 +2178,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2212,7 +2212,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2251,7 +2251,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2294,7 +2294,7 @@
Recursive: true,
IncludeItemTypes: ["Series"],
MinCommunityRating: 7.5,
Limit: 20,
Limit: 100,
Fields: DISCOVERY_CONTENT_FIELDS,
},
},
@@ -2328,7 +2328,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
{
@@ -2363,7 +2363,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2435,7 +2435,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
{
@@ -2468,7 +2468,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2502,7 +2502,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2536,7 +2536,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2563,7 +2563,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2599,7 +2599,7 @@
enabled: false,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Thumb",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2631,7 +2631,7 @@
enabled: false,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Thumb",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2663,7 +2663,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2708,7 +2708,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Poster",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2747,7 +2747,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Thumb",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2787,7 +2787,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Thumb",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
@@ -2834,7 +2834,7 @@
enabled: true,
userConfigurable: true,
itemLimit: 20,
sortOrder: "Random",
sortBy: "Random",
cardFormat: "Thumb",
ttl: CACHE_CONFIG.DISCOVERY_TTL,
queries: [
+21 -2
View File
@@ -8,6 +8,24 @@
const ERR = (...args) => console.error('[KefinTweaks SectionHelper]', ...args);
const ApiHelper = window.apiHelper || window.ApiHelper;
function isSortDirectionValue(value) {
const v = value == null ? '' : String(value).trim();
return v === 'Ascending' || v === 'Descending';
}
/** Legacy sortOrder was the field; sortOrder is now Ascending/Descending only. */
function normalizeInstanceSort(instanceConfig) {
const sortBy = instanceConfig?.sortBy == null ? '' : String(instanceConfig.sortBy).trim();
const order = instanceConfig?.sortOrder == null ? '' : String(instanceConfig.sortOrder).trim();
const legacyDirection = instanceConfig?.sortOrderDirection == null
? ''
: String(instanceConfig.sortOrderDirection).trim();
const out = { sortBy, sortOrder: isSortDirectionValue(order) ? order : '' };
if (order && !isSortDirectionValue(order) && !out.sortBy) out.sortBy = order;
if (isSortDirectionValue(legacyDirection)) out.sortOrder = legacyDirection;
return out;
}
const Config = () => window.KefinHomeConfig2 || window.KefinHomeScreen?.getConfig?.() || {};
const discoveryState = {
@@ -1213,8 +1231,9 @@
};
if (!hasTemplateQueries) {
if (instanceConfig.sortOrder) queryOptions.SortBy = instanceConfig.sortOrder;
if (instanceConfig.sortOrderDirection) queryOptions.SortOrder = instanceConfig.sortOrderDirection;
const sort = normalizeInstanceSort(instanceConfig);
if (sort.sortBy) queryOptions.SortBy = sort.sortBy;
if (sort.sortOrder) queryOptions.SortOrder = sort.sortOrder;
} else if (!queryOptions.IncludeItemTypes?.length) {
queryOptions.IncludeItemTypes = contentTypes;
}