fix(trackers): preserve Plex library context
This commit is contained in:
@@ -18,8 +18,9 @@ Future<void> collectEpisodesForShow(
|
||||
String showRatingKey, {
|
||||
required bool unwatchedOnly,
|
||||
required List<MediaItem> out,
|
||||
MediaItem? fallback,
|
||||
}) {
|
||||
return _collectPlayable(client, showRatingKey, unwatchedOnly: unwatchedOnly, out: out);
|
||||
return _collectPlayable(client, showRatingKey, unwatchedOnly: unwatchedOnly, out: out, fallback: fallback);
|
||||
}
|
||||
|
||||
/// Collect every episode of a single season into [out] via the same
|
||||
@@ -30,8 +31,9 @@ Future<void> collectEpisodesForSeason(
|
||||
String seasonRatingKey, {
|
||||
required bool unwatchedOnly,
|
||||
required List<MediaItem> out,
|
||||
MediaItem? fallback,
|
||||
}) {
|
||||
return _collectPlayable(client, seasonRatingKey, unwatchedOnly: unwatchedOnly, out: out);
|
||||
return _collectPlayable(client, seasonRatingKey, unwatchedOnly: unwatchedOnly, out: out, fallback: fallback);
|
||||
}
|
||||
|
||||
Future<void> _collectPlayable(
|
||||
@@ -39,11 +41,22 @@ Future<void> _collectPlayable(
|
||||
String parentId, {
|
||||
required bool unwatchedOnly,
|
||||
required List<MediaItem> out,
|
||||
MediaItem? fallback,
|
||||
}) async {
|
||||
final leaves = await client.fetchPlayableDescendants(parentId);
|
||||
for (final ep in leaves) {
|
||||
if (ep.kind != MediaKind.episode) continue;
|
||||
if (unwatchedOnly && ep.isWatched && !ep.hasActiveProgress) continue;
|
||||
out.add(ep);
|
||||
out.add(_withFallbackLibrary(ep, fallback));
|
||||
}
|
||||
}
|
||||
|
||||
MediaItem _withFallbackLibrary(MediaItem item, MediaItem? fallback) {
|
||||
if (fallback == null) return item;
|
||||
return item.copyWith(
|
||||
serverId: item.serverId ?? fallback.serverId,
|
||||
serverName: item.serverName ?? fallback.serverName,
|
||||
libraryId: item.libraryId ?? fallback.libraryId,
|
||||
libraryTitle: item.libraryTitle ?? fallback.libraryTitle,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -124,6 +124,8 @@ Future<MediaNavigationResult> navigateToMediaItem(
|
||||
title: mi.grandparentTitle ?? mi.parentTitle ?? mi.displayTitle,
|
||||
thumbPath: mi.grandparentThumbPath ?? mi.parentThumbPath,
|
||||
artPath: mi.grandparentArtPath,
|
||||
libraryId: mi.libraryId,
|
||||
libraryTitle: mi.libraryTitle,
|
||||
serverId: mi.serverId,
|
||||
serverName: mi.serverName,
|
||||
);
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
class PlexCacheParser {
|
||||
PlexCacheParser._();
|
||||
|
||||
static Map<String, dynamic>? extractMediaContainer(Map<String, dynamic>? cached) {
|
||||
final container = cached?['MediaContainer'];
|
||||
return container is Map<String, dynamic> ? container : null;
|
||||
}
|
||||
|
||||
static List<dynamic>? extractMetadataList(Map<String, dynamic>? cached) {
|
||||
if (cached == null) return null;
|
||||
return cached['MediaContainer']?['Metadata'] as List?;
|
||||
return extractMediaContainer(cached)?['Metadata'] as List?;
|
||||
}
|
||||
|
||||
static Map<String, dynamic>? extractFirstMetadata(Map<String, dynamic>? cached) {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import 'json_utils.dart';
|
||||
|
||||
final RegExp plexLibrarySectionPathPattern = RegExp(r'/(?:library|hubs)/sections/(\d+)');
|
||||
|
||||
int? plexLibrarySectionIdFromJson(Map<String, dynamic>? json) {
|
||||
if (json == null) return null;
|
||||
final direct = flexibleInt(json['librarySectionID']) ?? flexibleInt(json['targetLibrarySectionID']);
|
||||
if (direct != null) return direct;
|
||||
|
||||
for (final key in const ['librarySectionKey', 'key', 'hubKey']) {
|
||||
final parsed = plexLibrarySectionIdFromString(json[key]?.toString());
|
||||
if (parsed != null) return parsed;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int? plexLibrarySectionIdFromString(String? value) {
|
||||
if (value == null || value == 'shared') return null;
|
||||
final direct = int.tryParse(value);
|
||||
if (direct != null) return direct;
|
||||
final match = plexLibrarySectionPathPattern.firstMatch(value);
|
||||
return match == null ? null : int.tryParse(match.group(1)!);
|
||||
}
|
||||
|
||||
String? plexLibrarySectionTitleFromJson(Map<String, dynamic>? json) {
|
||||
return json?['librarySectionTitle']?.toString();
|
||||
}
|
||||
@@ -63,7 +63,8 @@ class WatchStateEvent with HierarchicalEventMixin {
|
||||
}) : globalKey = buildGlobalKey(serverId, itemId);
|
||||
|
||||
/// `serverId:librarySectionID`, matching [MediaLibrary.globalKey]. Null when
|
||||
/// the library section is unknown.
|
||||
/// the library section is unknown; tracker filters treat unknown as allowed
|
||||
/// only when no filter is configured.
|
||||
String? get librarySectionGlobalKey => librarySectionID != null ? buildGlobalKey(serverId, librarySectionID!) : null;
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user