diff --git a/lib/screens/libraries/tabs/library_browse_tab.dart b/lib/screens/libraries/tabs/library_browse_tab.dart index 720ec72a..b79dd012 100644 --- a/lib/screens/libraries/tabs/library_browse_tab.dart +++ b/lib/screens/libraries/tabs/library_browse_tab.dart @@ -626,9 +626,10 @@ class _LibraryBrowseTabState extends BaseLibraryTabState> fetchPage(int start, int size, AbortController? abort) async { final client = context.getMediaClientForLibrary(widget.library); + final filterParams = _buildFilterParams(); final query = libraryQueryFromPlexMap( - map: _buildFilterParams(), - libraryKind: widget.library.kind, + map: filterParams, + libraryKind: filterParams.containsKey('type') ? null : widget.library.kind, offset: start, limit: size, ); diff --git a/lib/services/jellyfin_client/parts/browse.dart b/lib/services/jellyfin_client/parts/browse.dart index 41afa544..3d7d6cf7 100644 --- a/lib/services/jellyfin_client/parts/browse.dart +++ b/lib/services/jellyfin_client/parts/browse.dart @@ -274,10 +274,9 @@ mixin _JellyfinBrowseMethods on MediaServerCacheMixin { MediaKind? libraryKind, AbortController? abort, }) async { - // [libraryKind] takes priority over any kind already on [query] — the - // browse tab passes the library's actual kind (Series, Movie) to override - // a less specific value. - final effective = (libraryKind != null && libraryKind != MediaKind.unknown) + // [libraryKind] is only a fallback for library-default browsing. Explicit + // grouping types on [query] (seasons/episodes) must keep priority. + final effective = (query.kind == null && libraryKind != null && libraryKind != MediaKind.unknown) ? query.copyWith(kind: libraryKind) : query; return fetchLibraryContent(libraryId, effective, abort: abort); diff --git a/test/services/jellyfin_client_urls_test.dart b/test/services/jellyfin_client_urls_test.dart index 0fcb7c25..f4cb4cbd 100644 --- a/test/services/jellyfin_client_urls_test.dart +++ b/test/services/jellyfin_client_urls_test.dart @@ -795,6 +795,36 @@ void main() { expect(captured!.queryParameters['ImageTypeLimit'], '1'); }); + test('fetchLibraryPagedContent uses library kind only when query kind is absent', () async { + final captured = []; + final scoped = JellyfinClient.forTesting( + connection: _conn(), + httpClient: MockClient((req) async { + captured.add(req.url); + return http.Response( + jsonEncode({'Items': const [], 'TotalRecordCount': 0}), + 200, + headers: {'content-type': 'application/json'}, + ); + }), + ); + addTearDown(scoped.close); + + await scoped.fetchLibraryPagedContent( + 'lib-1', + query: const LibraryQuery(offset: 0, limit: 20), + libraryKind: MediaKind.show, + ); + await scoped.fetchLibraryPagedContent( + 'lib-1', + query: const LibraryQuery(kind: MediaKind.episode, offset: 0, limit: 20), + libraryKind: MediaKind.show, + ); + + expect(captured[0].queryParameters['IncludeItemTypes'], 'Series'); + expect(captured[1].queryParameters['IncludeItemTypes'], 'Episode'); + }); + test('fetchClientSideEpisodeQueue pages past the first 200 episodes', () async { final starts = []; final pagedClient = JellyfinClient.forTesting(