diff --git a/lib/screens/libraries/tabs/library_collections_tab.dart b/lib/screens/libraries/tabs/library_collections_tab.dart index 55225cbc..8bb00ab6 100644 --- a/lib/screens/libraries/tabs/library_collections_tab.dart +++ b/lib/screens/libraries/tabs/library_collections_tab.dart @@ -38,7 +38,7 @@ class LibraryCollectionsTab extends BaseLibraryTab { class _LibraryCollectionsTabState extends BaseLibraryTabState with LibraryTabFocusMixin, PaginatedItemLoader { - static const int _pageSize = 200; + static const int _pageSize = 36; @override String get focusNodeDebugLabel => 'collections_first_item'; diff --git a/lib/services/jellyfin_client/parts/collections.dart b/lib/services/jellyfin_client/parts/collections.dart index 415f5104..2bb9fa01 100644 --- a/lib/services/jellyfin_client/parts/collections.dart +++ b/lib/services/jellyfin_client/parts/collections.dart @@ -5,7 +5,12 @@ mixin _JellyfinCollectionMethods on MediaServerCacheMixin { MediaServerHttpClient get _http; List _mapItems(Iterable> items); - static const int _collectionsPageSize = 200; + static const int _collectionsPageSize = 36; + static const String _collectionBrowseFields = 'ChildCount,SortName,Overview'; + static const Map _collectionImageQueryParameters = { + 'EnableImageTypes': 'Primary', + 'ImageTypeLimit': '1', + }; String? _boxSetsViewId; @@ -48,8 +53,9 @@ mixin _JellyfinCollectionMethods on MediaServerCacheMixin { 'Limit': pageSize.toString(), 'SortBy': 'SortName', 'SortOrder': 'Ascending', - 'Fields': _browseFields, - ...jellyfinImageQueryParameters, + 'Fields': _collectionBrowseFields, + 'EnableTotalRecordCount': 'false', + ..._collectionImageQueryParameters, }, abort: abort, ); diff --git a/test/services/jellyfin_client_urls_test.dart b/test/services/jellyfin_client_urls_test.dart index 7792bbc2..1e382c3f 100644 --- a/test/services/jellyfin_client_urls_test.dart +++ b/test/services/jellyfin_client_urls_test.dart @@ -1509,9 +1509,13 @@ void main() { expect(itemsRequest.queryParameters['IncludeItemTypes'], 'BoxSet'); expect(itemsRequest.queryParameters['Recursive'], 'true'); expect(itemsRequest.queryParameters['StartIndex'], '0'); - expect(itemsRequest.queryParameters['Limit'], '200'); + expect(itemsRequest.queryParameters['Limit'], '36'); expect(itemsRequest.queryParameters['SortBy'], 'SortName'); expect(itemsRequest.queryParameters['SortOrder'], 'Ascending'); + expect(itemsRequest.queryParameters['Fields'], 'ChildCount,SortName,Overview'); + expect(itemsRequest.queryParameters['EnableTotalRecordCount'], 'false'); + expect(itemsRequest.queryParameters['EnableImageTypes'], 'Primary'); + expect(itemsRequest.queryParameters['ImageTypeLimit'], '1'); }); test('fetchCollectionsPage uses requested collection page bounds', () async { @@ -1555,6 +1559,43 @@ void main() { expect(itemsRequest!.queryParameters['ParentId'], 'lib-boxsets'); expect(itemsRequest!.queryParameters['StartIndex'], '20'); expect(itemsRequest!.queryParameters['Limit'], '10'); + expect(itemsRequest!.queryParameters['EnableTotalRecordCount'], 'false'); + }); + + test('fetchCollectionsPage uses sentinel total when total count is missing', () async { + final mock = MockClient((req) async { + if (req.url.path == '/Users/user-1/Views') { + return http.Response( + jsonEncode({ + 'Items': [ + {'Id': 'lib-boxsets', 'Name': 'Collections', 'CollectionType': 'boxsets'}, + ], + }), + 200, + headers: {'content-type': 'application/json'}, + ); + } + if (req.url.path == '/Items') { + return http.Response( + jsonEncode({ + 'Items': [ + {'Id': 'collection-1', 'Name': 'Collection 1', 'Type': 'BoxSet'}, + {'Id': 'collection-2', 'Name': 'Collection 2', 'Type': 'BoxSet'}, + ], + }), + 200, + headers: {'content-type': 'application/json'}, + ); + } + return http.Response('not found', 404); + }); + final client = JellyfinClient.forTesting(connection: _conn(), httpClient: mock); + addTearDown(client.close); + + final page = await client.fetchCollectionsPage('lib-movies', size: 2); + + expect(page.items.map((c) => c.id).toList(), ['collection-1', 'collection-2']); + expect(page.totalCount, 3); }); test('walks boxsets view in pages', () async { @@ -1594,7 +1635,7 @@ void main() { expect(collections.map((c) => c.id).toList(), ['collection-1', 'collection-2']); expect(itemRequests.map((u) => u.queryParameters['StartIndex']).toList(), ['0', '1']); - expect(itemRequests.every((u) => u.queryParameters['Limit'] == '200'), isTrue); + expect(itemRequests.every((u) => u.queryParameters['Limit'] == '36'), isTrue); }); test('returns empty when boxsets view is missing', () async {