fix(libraries): exclude episodes from mixed roots

close #1675
This commit is contained in:
edde746
2026-07-25 09:13:00 +02:00
parent 9a6f48a4cb
commit 0959cd3040
11 changed files with 129 additions and 31 deletions
@@ -428,7 +428,8 @@ mixin _JellyfinBrowseMethods on MediaServerCacheMixin {
}) async {
// [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)
final effective =
(query.kind == null && query.includeKinds.isEmpty && libraryKind != null && libraryKind != MediaKind.unknown)
? query.copyWith(kind: libraryKind)
: query;
return fetchLibraryContent(libraryId, effective, abort: abort);
+5
View File
@@ -273,6 +273,7 @@ class JellyfinMappers {
backend: MediaBackend.jellyfin,
title: view['Name'] as String? ?? t.libraries.fallbackTitle,
kind: _libraryKindFromCollectionType(collectionType, view['Type'] as String?),
defaultBrowseKinds: _defaultBrowseKindsFromCollectionType(collectionType),
updatedAt: jellyfinIsoToEpochSeconds(view['DateLastSaved'] as String? ?? view['DateModified'] as String?),
createdAt: jellyfinIsoToEpochSeconds(view['DateCreated'] as String?),
hidden: false,
@@ -334,6 +335,10 @@ class JellyfinMappers {
return MediaKind.fromString(type);
}
static List<MediaKind> _defaultBrowseKindsFromCollectionType(String? collectionType) {
return collectionType?.toLowerCase() == 'mixed' ? const [MediaKind.movie, MediaKind.show] : const <MediaKind>[];
}
static Map<String, dynamic>? _userData(Map<String, dynamic> item) {
final ud = item['UserData'];
return ud is Map<String, dynamic> ? ud : null;
+19 -5
View File
@@ -52,9 +52,16 @@ class PlexLibraryQueryTranslator implements LibraryQueryTranslator {
@override
Map<String, String> toQueryParameters(LibraryQuery query) {
final filters = <String, String>{};
final kindNumber = _plexTypeNumberFor(query.kind);
if (kindNumber != null) {
filters['type'] = kindNumber.toString();
if (query.includeKinds.isNotEmpty) {
final kindNumbers = query.includeKinds.map(_plexTypeNumberFor).whereType<int>().join(',');
if (kindNumbers.isNotEmpty) {
filters['type'] = kindNumbers;
}
} else {
final kindNumber = _plexTypeNumberFor(query.kind);
if (kindNumber != null) {
filters['type'] = kindNumber.toString();
}
}
final sort = query.sort;
if (sort != null) {
@@ -221,7 +228,7 @@ class JellyfinLibraryQueryTranslator implements LibraryQueryTranslator {
'StartIndex': query.offset.toString(),
'Limit': query.limit.toString(),
'EnableTotalRecordCount': 'true',
'IncludeItemTypes': _includeTypesFor(query.kind),
'IncludeItemTypes': _includeTypesFor(query),
'Fields': fields,
...jellyfinImageQueryParameters,
};
@@ -263,7 +270,14 @@ class JellyfinLibraryQueryTranslator implements LibraryQueryTranslator {
return params;
}
static String _includeTypesFor(MediaKind? kind) {
static String _includeTypesFor(LibraryQuery query) {
if (query.includeKinds.isNotEmpty) {
return query.includeKinds.map(_includeTypesForKind).join(',');
}
return _includeTypesForKind(query.kind);
}
static String _includeTypesForKind(MediaKind? kind) {
return switch (kind) {
MediaKind.movie => 'Movie',
MediaKind.show => 'Series',