diff options
| author | Cody Robibero <cody@robibe.ro> | 2026-08-30 13:29:13 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-30 13:29:13 -0400 |
| commit | 4962e4ec33dcc0f208eef7ccf72a78d26c5f2ae8 (patch) | |
| tree | 1b2bd54ea27d06ea17ab3d176b48e357d01d4f0a /Jellyfin.Server.Implementations | |
| parent | 24288e79a9a576ead991afe1b96295ac8a36fad5 (diff) | |
| parent | 27d898e59e5c225baa3db0ee114f1c4034b74e31 (diff) | |
Merge pull request #17735 from Shadowghost/fix-season-child-count
Count a season's episodes by the season they belong to
Diffstat (limited to 'Jellyfin.Server.Implementations')
| -rw-r--r-- | Jellyfin.Server.Implementations/Item/ItemCountService.cs | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/Jellyfin.Server.Implementations/Item/ItemCountService.cs b/Jellyfin.Server.Implementations/Item/ItemCountService.cs index c42b5f9581..14b120363f 100644 --- a/Jellyfin.Server.Implementations/Item/ItemCountService.cs +++ b/Jellyfin.Server.Implementations/Item/ItemCountService.cs @@ -319,7 +319,7 @@ public class ItemCountService : IItemCountService } /// <inheritdoc/> - public Dictionary<Guid, int> GetChildCountBatch(IReadOnlyList<Guid> parentIds, Guid? userId) + public Dictionary<Guid, int> GetChildCountBatch(IReadOnlyList<Guid> parentIds, User? user) { ArgumentNullException.ThrowIfNull(parentIds); @@ -332,20 +332,32 @@ public class ItemCountService : IItemCountService var parentIdsArray = parentIds.ToArray(); + var includeVirtual = user is null || user.DisplayMissingEpisodes; + var hierarchicalCounts = dbContext.BaseItems - .Where(b => b.ParentId.HasValue) + .Where(b => b.ParentId.HasValue && !b.SeasonId.HasValue && (includeVirtual || !b.IsVirtualItem)) .WhereOneOrMany(parentIdsArray, b => b.ParentId!.Value) .GroupBy(b => b.ParentId!.Value) .Select(g => new { ParentId = g.Key, Count = g.Count() }) .ToDictionary(x => x.ParentId, x => x.Count); + // An episode is a child of its season even when it is not stored under one: with a flat + // structure ParentId points at the series, so counting by ParentId alone leaves the season + // empty and counts its episodes towards the series instead. + var seasonCounts = dbContext.BaseItems + .Where(b => b.SeasonId.HasValue && (includeVirtual || !b.IsVirtualItem)) + .WhereOneOrMany(parentIdsArray, b => b.SeasonId!.Value) + .GroupBy(b => b.SeasonId!.Value) + .Select(g => new { SeasonId = g.Key, Count = g.Count() }) + .ToDictionary(x => x.SeasonId, x => x.Count); + var linkedCounts = dbContext.LinkedChildren .WhereOneOrMany(parentIdsArray, lc => lc.ParentId) .GroupBy(lc => lc.ParentId) .Select(g => new { ParentId = g.Key, Count = g.Count() }) .ToDictionary(x => x.ParentId, x => x.Count); - var mergedChildCounts = GetMergedChildCounts(dbContext, parentIdsArray); + var mergedChildCounts = GetMergedChildCounts(dbContext, parentIdsArray, includeVirtual); var result = new Dictionary<Guid, int>(); foreach (var parentId in parentIds) @@ -356,7 +368,8 @@ public class ItemCountService : IItemCountService continue; } - var hierarchicalCount = hierarchicalCounts.GetValueOrDefault(parentId, 0); + var hierarchicalCount = hierarchicalCounts.GetValueOrDefault(parentId, 0) + + seasonCounts.GetValueOrDefault(parentId, 0); var linkedCount = linkedCounts.GetValueOrDefault(parentId, 0); result[parentId] = linkedCount > 0 ? linkedCount : hierarchicalCount; @@ -365,7 +378,7 @@ public class ItemCountService : IItemCountService return result; } - private static Dictionary<Guid, int> GetMergedChildCounts(JellyfinDbContext dbContext, IReadOnlyList<Guid> parentIds) + private static Dictionary<Guid, int> GetMergedChildCounts(JellyfinDbContext dbContext, IReadOnlyList<Guid> parentIds, bool includeVirtual) { var mergedGroups = GetPresentationKeyGroups(dbContext, parentIds) .Where(group => group.Value.Count > 1) @@ -380,10 +393,16 @@ public class ItemCountService : IItemCountService var memberIds = mergedGroups.SelectMany(group => group.Value).Distinct().ToArray(); var children = dbContext.BaseItems .AsNoTracking() - .Where(b => b.ParentId.HasValue) + .Where(b => b.ParentId.HasValue && !b.SeasonId.HasValue && (includeVirtual || !b.IsVirtualItem)) .WhereOneOrMany(memberIds, b => b.ParentId!.Value) .Select(b => new { ParentId = b.ParentId!.Value, b.Id, b.PresentationUniqueKey }) .ToArray() + .Concat(dbContext.BaseItems + .AsNoTracking() + .Where(b => b.SeasonId.HasValue && (includeVirtual || !b.IsVirtualItem)) + .WhereOneOrMany(memberIds, b => b.SeasonId!.Value) + .Select(b => new { ParentId = b.SeasonId!.Value, b.Id, b.PresentationUniqueKey }) + .ToArray()) .GroupBy(b => b.ParentId) .ToDictionary( g => g.Key, |
