From 7c331e51e6f5f77cf1076101a261777b5c832125 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Tue, 21 Apr 2026 17:35:55 +0200 Subject: [PATCH] fix: auto-skip credits honors auto-play-next close #901 --- lib/screens/video_player_screen.dart | 1 + .../video_controls/video_controls.dart | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/screens/video_player_screen.dart b/lib/screens/video_player_screen.dart index 64e0496f..36a05e72 100644 --- a/lib/screens/video_player_screen.dart +++ b/lib/screens/video_player_screen.dart @@ -3440,6 +3440,7 @@ class VideoPlayerScreenState extends State with WidgetsBindin } }, onBack: _handleBackButton, + onReachedEnd: () => _onVideoCompleted(true), canControl: canControl, hasFirstFrame: _hasFirstFrame, playNextFocusNode: _showPlayNextDialog ? _playNextConfirmFocusNode : null, diff --git a/lib/widgets/video_controls/video_controls.dart b/lib/widgets/video_controls/video_controls.dart index 38fa9f59..f723c177 100644 --- a/lib/widgets/video_controls/video_controls.dart +++ b/lib/widgets/video_controls/video_controls.dart @@ -79,6 +79,7 @@ Widget plexVideoControlsBuilder( Function(SubtitleTrack)? onSecondarySubtitleTrackChanged, Function(Duration position)? onSeekCompleted, VoidCallback? onBack, + VoidCallback? onReachedEnd, bool canControl = true, ValueNotifier? hasFirstFrame, FocusNode? playNextFocusNode, @@ -116,6 +117,7 @@ Widget plexVideoControlsBuilder( onSecondarySubtitleTrackChanged: onSecondarySubtitleTrackChanged, onSeekCompleted: onSeekCompleted, onBack: onBack, + onReachedEnd: onReachedEnd, canControl: canControl, hasFirstFrame: hasFirstFrame, playNextFocusNode: playNextFocusNode, @@ -158,6 +160,11 @@ class PlexVideoControls extends StatefulWidget { /// Called when back button is pressed (for Watch Together session leave confirmation) final VoidCallback? onBack; + /// Called when the video has effectively reached the end (e.g. credits extend + /// to EOF and can't be seeked past). Parent should route this into its + /// normal completion flow so the auto-play-next setting is honored. + final VoidCallback? onReachedEnd; + /// Whether the user can control playback (false in host-only mode for non-host). final bool canControl; @@ -231,6 +238,7 @@ class PlexVideoControls extends StatefulWidget { this.onSecondarySubtitleTrackChanged, this.onSeekCompleted, this.onBack, + this.onReachedEnd, this.canControl = true, this.hasFirstFrame, this.playNextFocusNode, @@ -524,13 +532,10 @@ class _PlexVideoControlsState extends State with WindowListen final isAtEnd = duration > Duration.zero && (duration - endTime).inMilliseconds <= 1000; if (marker.isCredits && isAtEnd) { - // Credits extend to end of video — don't seek (unreliable due to - // position stream throttling). Go to next episode or exit player. - if (widget.onNext != null) { - widget.onNext!.call(); - } else { - widget.onBack?.call(); - } + // Seeking to EOF is unreliable due to position stream throttling, + // so pause and defer to the parent's completion flow. + await widget.player.pause(); + widget.onReachedEnd?.call(); } else { await _seekToPosition(endTime); }