From ec990be12af3856eea597ba7ebdd5dbfa5b01ace Mon Sep 17 00:00:00 2001 From: dkanada Date: Mon, 4 May 2026 12:06:11 +0900 Subject: [PATCH] fix person TotalRecordCount when limit is applied --- .../Library/LibraryManager.cs | 46 +++++++++++-------- Jellyfin.Api/Controllers/PersonsController.cs | 8 ++-- .../Item/PeopleRepository.cs | 18 ++++++-- .../Library/ILibraryManager.cs | 2 +- .../Persistence/IPeopleRepository.cs | 8 ++-- 5 files changed, 51 insertions(+), 31 deletions(-) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index eee87c4d8b..a7062914cf 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -34,14 +34,11 @@ using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.MediaSegments; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Sorting; -using MediaBrowser.Controller.Trickplay; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -2918,7 +2915,7 @@ namespace Emby.Server.Implementations.Library public IReadOnlyList GetPeople(InternalPeopleQuery query) { - return _peopleRepository.GetPeople(query); + return _peopleRepository.GetPeople(query).Items; } public IReadOnlyList GetPeople(BaseItem item) @@ -2939,24 +2936,33 @@ namespace Emby.Server.Implementations.Library return []; } - public IReadOnlyList GetPeopleItems(InternalPeopleQuery query) + public QueryResult GetPeopleItems(InternalPeopleQuery query) { - return _peopleRepository.GetPeopleNames(query) - .Select(i => + var queryResult = _peopleRepository.GetPeople(query); + var baseItems = queryResult.Items.Select(i => + { + try + { + return GetPerson(i.Name); + } + catch (Exception ex) + { + _logger.LogError(ex, "error retrieving BaseItem for person: {0}", i.Name); + return null; + } + }) + .Where(i => i is not null) + .Where(i => query.User is null || i!.IsVisible(query.User)) + .OfType() + .ToList() + .AsReadOnly(); + + return new QueryResult { - try - { - return GetPerson(i); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error getting person"); - return null; - } - }) - .Where(i => i is not null) - .Where(i => query.User is null || i!.IsVisible(query.User)) - .ToList()!; // null values are filtered out + StartIndex = queryResult.StartIndex, + TotalRecordCount = queryResult.TotalRecordCount, + Items = baseItems, + }; } public IReadOnlyList GetPeopleNames(InternalPeopleQuery query) diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index 2b2afb0fe6..bc58580741 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -106,9 +106,11 @@ public class PersonsController : BaseJellyfinApiController }); return new QueryResult( - peopleItems - .Select(person => _dtoService.GetItemByNameDto(person, dtoOptions, null, user)) - .ToArray()); + peopleItems.StartIndex, + peopleItems.TotalRecordCount, + peopleItems.Items + .Select(person => _dtoService.GetItemByNameDto(person, dtoOptions, null, user)) + .ToArray()); } /// diff --git a/Jellyfin.Server.Implementations/Item/PeopleRepository.cs b/Jellyfin.Server.Implementations/Item/PeopleRepository.cs index ad9953d1b6..576e786cb7 100644 --- a/Jellyfin.Server.Implementations/Item/PeopleRepository.cs +++ b/Jellyfin.Server.Implementations/Item/PeopleRepository.cs @@ -1,14 +1,13 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; using Jellyfin.Data.Enums; using Jellyfin.Database.Implementations; using Jellyfin.Database.Implementations.Entities; -using Jellyfin.Database.Implementations.Entities.Libraries; using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Querying; using Microsoft.EntityFrameworkCore; namespace Jellyfin.Server.Implementations.Item; @@ -30,7 +29,7 @@ public class PeopleRepository(IDbContextFactory dbProvider, I private readonly IDbContextFactory _dbProvider = dbProvider; /// - public IReadOnlyList GetPeople(InternalPeopleQuery filter) + public QueryResult GetPeople(InternalPeopleQuery filter) { using var context = _dbProvider.CreateDbContext(); var dbQuery = TranslateQuery(context.Peoples.AsNoTracking(), context, filter); @@ -48,12 +47,23 @@ public class PeopleRepository(IDbContextFactory dbProvider, I dbQuery = dbQuery.OrderBy(e => e.Name); } + var count = dbQuery.Count(); + if (filter.StartIndex.HasValue && filter.StartIndex > 0) + { + dbQuery = dbQuery.Skip(filter.StartIndex.Value); + } + if (filter.Limit > 0) { dbQuery = dbQuery.Take(filter.Limit); } - return dbQuery.AsEnumerable().Select(Map).ToArray(); + return new QueryResult + { + StartIndex = filter.StartIndex ?? 0, + TotalRecordCount = count, + Items = dbQuery.AsEnumerable().Select(Map).ToArray(), + }; } /// diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index df1c98f3f7..a96667545e 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -514,7 +514,7 @@ namespace MediaBrowser.Controller.Library /// /// The query. /// List<Person>. - IReadOnlyList GetPeopleItems(InternalPeopleQuery query); + QueryResult GetPeopleItems(InternalPeopleQuery query); /// /// Updates the people. diff --git a/MediaBrowser.Controller/Persistence/IPeopleRepository.cs b/MediaBrowser.Controller/Persistence/IPeopleRepository.cs index 418289cb4c..a89f3ef9ee 100644 --- a/MediaBrowser.Controller/Persistence/IPeopleRepository.cs +++ b/MediaBrowser.Controller/Persistence/IPeopleRepository.cs @@ -1,13 +1,15 @@ #nullable disable -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.Persistence; +/// +/// Provides methods for accessing Peoples. +/// public interface IPeopleRepository { /// @@ -15,7 +17,7 @@ public interface IPeopleRepository /// /// The query. /// The list of people matching the filter. - IReadOnlyList GetPeople(InternalPeopleQuery filter); + QueryResult GetPeople(InternalPeopleQuery filter); /// /// Updates the people.