diff options
| author | theguymadmax <theguymadmax@proton.me> | 2026-08-19 18:12:10 -0400 |
|---|---|---|
| committer | theguymadmax <theguymadmax@proton.me> | 2026-08-19 18:34:21 -0400 |
| commit | 80fe8c67e97a8b239bd733eb295222ca52c5126d (patch) | |
| tree | f7c4333d75f27c355b846fb030be463f66ec3679 | |
| parent | 19d919f8be44f9f863d5839ac411216b0f1dee4e (diff) | |
Fix latest items for mixed libraries
| -rw-r--r-- | Emby.Server.Implementations/Library/UserViewManager.cs | 6 | ||||
| -rw-r--r-- | Jellyfin.Server.Implementations/Item/BaseItemRepository.Querying.cs | 64 |
2 files changed, 53 insertions, 17 deletions
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index 9512b0ffd7..49d76e195d 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -396,6 +396,12 @@ namespace Emby.Server.Implementations.Library query.Limit = limit; return _libraryManager.GetLatestItemList(query, parents, CollectionType.movies); } + + if (collectionType is null) + { + query.Limit = limit; + return _libraryManager.GetLatestItemList(query, parents, CollectionType.unknown); + } } return _libraryManager.GetItemList(query, parents); diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.Querying.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.Querying.cs index c7acf72043..c9e08b1b5d 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.Querying.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.Querying.cs @@ -110,7 +110,7 @@ public sealed partial class BaseItemRepository PrepareFilterQuery(filter); // Early exit if collection type is not supported - if (collectionType is not CollectionType.movies and not CollectionType.tvshows and not CollectionType.music) + if (collectionType is not CollectionType.movies and not CollectionType.tvshows and not CollectionType.music and not CollectionType.unknown) { return []; } @@ -121,30 +121,27 @@ public sealed partial class BaseItemRepository var baseQuery = PrepareItemQuery(context, filter); baseQuery = TranslateQuery(baseQuery, context, filter); - if (collectionType == CollectionType.tvshows) + if (collectionType is CollectionType.tvshows) { return GetLatestTvShowItems(context, baseQuery, filter, limit); } if (collectionType is CollectionType.movies) { - // Pick, per PresentationUniqueKey, the newest item; return the newest `limit` of those. - // Build up until limit by streaming through results and deduplicating on the fly. - var orderedIds = baseQuery - .Where(e => e.PresentationUniqueKey != null) - .OrderByDescending(e => e.DateCreated) - .ThenByDescending(e => e.Id) - .Select(e => new { e.Id, e.PresentationUniqueKey }); - - // DistinctBy and Take are lazy, so enumeration stops as soon as limit distinct keys are read. - var firstIds = orderedIds - .AsEnumerable() - .DistinctBy(row => row.PresentationUniqueKey) - .Select(row => row.Id) + return GetLatestMovieItems(context, baseQuery, filter, limit); + } + + if (collectionType is CollectionType.unknown) + { + var moviesQuery = baseQuery.Where(e => e.SeriesName == null); + var latestMovies = GetLatestMovieItems(context, moviesQuery, filter, limit); + var latestShows = GetLatestTvShowItems(context, baseQuery, filter, limit); + + return latestMovies.Concat(latestShows) + .OrderByDescending(dto => dto.DateCreated) + .ThenByDescending(dto => dto.Id) .Take(limit ?? int.MaxValue) .ToList(); - - return LoadLatestByIds(context, firstIds, filter); } var musicAlbumTypeName = _itemTypeLookup.BaseItemKindNames[BaseItemKind.MusicAlbum]!; @@ -226,6 +223,39 @@ public sealed partial class BaseItemRepository } /// <summary> + /// Gets the latest movies, deduplicated so each movie only appears once. + /// </summary> + /// <param name="context">The database context.</param> + /// <param name="baseQuery">The query to pull movies from, with filters already applied.</param> + /// <param name="filter">The original query filter, used when loading the final items.</param> + /// <param name="limit">How many items to return.</param> + /// <returns>The latest movies, newest first.</returns> + private IReadOnlyList<BaseItemDto> GetLatestMovieItems( + JellyfinDbContext context, + IQueryable<BaseItemEntity> baseQuery, + InternalItemsQuery filter, + int? limit) + { + // Pick, per PresentationUniqueKey, the newest item; return the newest `limit` of those. + // Build up until limit by streaming through results and deduplicating on the fly. + var orderedIds = baseQuery + .Where(e => e.PresentationUniqueKey != null) + .OrderByDescending(e => e.DateCreated) + .ThenByDescending(e => e.Id) + .Select(e => new { e.Id, e.PresentationUniqueKey }); + + // DistinctBy and Take are lazy, so enumeration stops as soon as limit distinct keys are read. + var firstIds = orderedIds + .AsEnumerable() + .DistinctBy(row => row.PresentationUniqueKey) + .Select(row => row.Id) + .Take(limit ?? int.MaxValue) + .ToList(); + + return LoadLatestByIds(context, firstIds, filter); + } + + /// <summary> /// Gets the latest TV show items with smart Season/Series container selection. /// </summary> /// <remarks> |
