fix(playback): keep Plex playlist queue when entering the player

close #978
This commit is contained in:
edde746
2026-05-04 21:34:14 +02:00
parent f573eda657
commit fdaff3687d
4 changed files with 66 additions and 18 deletions
@@ -67,6 +67,15 @@ class PlaybackStateProvider with ChangeNotifier, DisposableChangeNotifierMixin {
/// Whether any queue-based playback is active
bool get isQueueActive => _playQueueId != null && _isQueueMode;
/// Whether [item] belongs to the currently active queue. True for Plex
/// items the server-side queue stamped with a `playQueueItemId`, and for
/// items present in a Jellyfin local queue (synthetic id). Gates the
/// player's "preserve vs. wipe launcher-set queue" decision in both
/// [VideoPlayerScreen.initState] and `_ensurePlayQueue`, so a playlist
/// or collection queue survives entry into the player instead of being
/// replaced with a show queue.
bool isItemInActiveQueue(MediaItem item) => isQueueActive && playQueueItemIdFor(item) != null;
/// The context key (show/season/playlist ratingKey) for the current session
String? get shuffleContextKey => _contextKey;
@@ -34,20 +34,19 @@ extension _VideoPlayerEpisodeQueueMethods on VideoPlayerScreenState {
return;
}
// Check if there's already an active queue for THIS show.
// A leftover queue from a different show or — more importantly —
// from a different backend (Jellyfin's local queue is published
// here too) would otherwise mask the new show's navigation.
final existingContextKey = playbackState.shuffleContextKey;
final isQueueActive = playbackState.isQueueActive;
if (isQueueActive && existingContextKey == showRatingKey) {
// Preserve any queue this item belongs to — playlist, collection,
// or same-show queue. `isItemInActiveQueue` is the same gate
// VideoPlayerScreen.initState uses; a context-key check alone would
// wipe a playlist queue (its key is the playlist id, not the show).
// Only when the active queue is genuinely stale (item not in it)
// do we clobber and create a fresh show queue.
if (playbackState.isItemInActiveQueue(_currentMetadata)) {
playbackState.setCurrentItem(_currentMetadata);
appLogger.d('Using existing play queue (context: $existingContextKey)');
appLogger.d('Using existing play queue (context: ${playbackState.shuffleContextKey})');
return;
}
if (isQueueActive) {
appLogger.d('Resetting stale play queue (was: $existingContextKey, now: $showRatingKey)');
if (playbackState.isQueueActive) {
appLogger.d('Resetting stale play queue (was: ${playbackState.shuffleContextKey}, now: $showRatingKey)');
playbackState.clearShuffle();
}
+1 -2
View File
@@ -449,8 +449,7 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen> with WidgetsBindin
// playback (continue-watching, direct episode tap with no queue
// launcher) clear any stale queue so prev/next stays consistent.
final meta = widget.metadata;
final inActiveQueue = playbackState.isQueueActive && playbackState.playQueueItemIdFor(meta) != null;
if (inActiveQueue) {
if (playbackState.isItemInActiveQueue(meta)) {
playbackState.setCurrentItem(meta);
} else {
playbackState.clearShuffle();