diff --git a/lib/pages/player/player_logic.dart b/lib/pages/player/player_logic.dart index c9c94aa..5920184 100644 --- a/lib/pages/player/player_logic.dart +++ b/lib/pages/player/player_logic.dart @@ -313,6 +313,14 @@ class PlayerLogic extends ChangeNotifier { void onLifecycle(AppLifecycleState state) { if (state != AppLifecycleState.resumed) unawaited(saveCurrentProgress()); if (state == AppLifecycleState.resumed) { + // 部分机型退出画中画不会回调 onPipChanged(false):回前台先兜底复位, + // 否则 chromeHidden 恒为 true,播放浮层与首页底栏都会消失。 + if (pip || pipPreparing) { + pip = false; + pipPreparing = false; + notify(); + notifyImmersive(); + } // 签名地址有有效期:回前台时若票据已过期,重新取一张再起播, // 否则会撞上 403(契约 §1.4) final episode = trackedEpisode; diff --git a/test/player/player_logic_test.dart b/test/player/player_logic_test.dart index 44084d9..c0235c2 100644 --- a/test/player/player_logic_test.dart +++ b/test/player/player_logic_test.dart @@ -187,6 +187,34 @@ void main() { expect(logic.pip, isFalse); }); + + test('should_clear_stale_pip_when_app_returns_to_foreground', () async { + final factory = _RecordingFactory(); + final drama = _drama('signal'); + final logic = _logic(FakeWatchHistory()); + final immersive = []; + logic.attach( + PlayerPage(drama: drama, initialIndex: 0), + isMounted: () => true, + ); + logic.onImmersiveChanged = immersive.add; + logic.start(factory: factory.create, coordinator: PlaybackCoordinator()); + await _drain(logic); + + // 模拟画中画已进入但退出时没有回调 false。 + logic.onPipChanged(true); + expect(logic.chromeHidden, isTrue); + + logic.onLifecycle(AppLifecycleState.resumed); + + expect(logic.pip, isFalse); + expect(logic.pipPreparing, isFalse); + expect(logic.chromeHidden, isFalse); + expect(immersive.last, isFalse); + + logic.dispose(); + await _drain(logic); + }); }); group('history writes', () {