diff --git a/lib/mpv/player/player_native.dart b/lib/mpv/player/player_native.dart index 5aa076e6..5a44b4c9 100644 --- a/lib/mpv/player/player_native.dart +++ b/lib/mpv/player/player_native.dart @@ -305,11 +305,21 @@ class PlayerNative implements Player { } void _updateSelectedSubtitleTrack(dynamic trackId) { - _updateSelectedTrack( - trackId, - _state.tracks.subtitle.cast().toList(), - (selection, track) => selection.copyWith(subtitle: track), - ); + final id = trackId?.toString(); + SubtitleTrack? selectedTrack; + + if (id == null || id == 'no') { + // Explicitly set SubtitleTrack.off so episode navigation can detect "subtitles off" + selectedTrack = SubtitleTrack.off; + } else { + selectedTrack = _state.tracks.subtitle.cast().firstWhere( + (t) => t?.id == id, + orElse: () => null, + ); + } + + _state = _state.copyWith(track: _state.track.copyWith(subtitle: selectedTrack)); + _trackController.add(_state.track); } void _updateSelectedTrack( diff --git a/lib/screens/season_detail_screen.dart b/lib/screens/season_detail_screen.dart index febd8a07..36a302aa 100644 --- a/lib/screens/season_detail_screen.dart +++ b/lib/screens/season_detail_screen.dart @@ -41,6 +41,8 @@ class _SeasonDetailScreenState extends State with ItemUpdata List _episodes = []; bool _isLoadingEpisodes = false; bool _watchStateChanged = false; + // Capture keyboard mode once at init to avoid rebuild dependency + bool _initialKeyboardMode = false; /// Get the correct PlexClient for this season's server PlexClient? _getClientForSeason(BuildContext context) { @@ -55,6 +57,8 @@ class _SeasonDetailScreenState extends State with ItemUpdata super.initState(); // Initialize the client once in initState WidgetsBinding.instance.addPostFrameCallback((_) { + // Capture keyboard mode once to avoid rebuild dependency when mode changes + _initialKeyboardMode = InputModeTracker.isKeyboardMode(context); _client = _getClientForSeason(context); _loadEpisodes(); }); @@ -165,7 +169,7 @@ class _SeasonDetailScreenState extends State with ItemUpdata client: _client, isOffline: widget.isOffline, localPosterPath: localPosterPath, - autofocus: index == 0 && InputModeTracker.isKeyboardMode(context), + autofocus: index == 0 && _initialKeyboardMode, onTap: () async { await navigateToVideoPlayerWithRefresh( context, diff --git a/lib/widgets/video_controls/video_controls.dart b/lib/widgets/video_controls/video_controls.dart index 81dc7d0e..406bcdd7 100644 --- a/lib/widgets/video_controls/video_controls.dart +++ b/lib/widgets/video_controls/video_controls.dart @@ -1266,18 +1266,16 @@ class _PlexVideoControlsState extends State with WindowListen final key = event.logicalKey; final isPlayPauseKey = _isPlayPauseKey(event); - // Handle play/pause via focus when navigation is enabled (TV/gamepad) - // When navigation is disabled, the global handler (_handleGlobalKeyEvent) handles it - if (_videoPlayerNavigationEnabled || isMobile) { - if (_isPlayPauseActivation(event)) { - widget.player.playOrPause(); - _showControlsWithFocus(requestFocus: _videoPlayerNavigationEnabled); - return KeyEventResult.handled; - } - // Swallow other play/pause events (e.g., key up/repeat) to prevent focus side effects - if (isPlayPauseKey) { - return KeyEventResult.handled; + // Always consume play/pause keys to prevent propagation to background routes + // On TV/mobile, handle play/pause here; on desktop, the global handler does it + if (isPlayPauseKey) { + if (_videoPlayerNavigationEnabled || isMobile) { + if (_isPlayPauseActivation(event)) { + widget.player.playOrPause(); + _showControlsWithFocus(requestFocus: _videoPlayerNavigationEnabled); + } } + return KeyEventResult.handled; } // Handle Back/Escape: show controls if hidden, navigate back if visible