diff --git a/lib/pages/player/player_logic.dart b/lib/pages/player/player_logic.dart index acdbb65..4685810 100644 --- a/lib/pages/player/player_logic.dart +++ b/lib/pages/player/player_logic.dart @@ -133,6 +133,29 @@ class PlayerLogic extends ChangeNotifier { static const _iosAutoPipPrefKey = 'player.ios.autoEnterPip'; bool iosAutoPipEnabled = false; + /// 播放页前台活跃标志:沉浸流切走 tab / 独立页关闭后置 false, + /// 此时退后台不再自动拉起画中画(影子只同步不拉起)。 + bool pipPageActive = false; + + /// 由播放视图同步活跃标志;离开播放页时撤销影子的自动小窗资格, + /// 重新进入时重建影子待命(切走期间视图可能被卸载、逻辑实例已换新)。 + void setPipPageActive(bool active) { + debugPrint('pip: page-active -> $active'); + if (pipPageActive == active) return; + pipPageActive = active; + if (!active && iosDevice) { + unawaited(pictureInPicture.disarmAutoEnter()); + return; + } + if (active && iosDevice && iosAutoPipEnabled && !pip) { + final episode = trackedEpisode; + if (episode != null) { + debugPrint('pip: page re-entered, ensure shadow standby'); + unawaited(_ensureIosShadowStandby(episode)); + } + } + } + /// 画中画还原信号:自增通知视频表面回退占位重新等首帧(防回前台黑屏)。 int pipResumeToken = 0; @@ -925,7 +948,14 @@ class PlayerLogic extends ChangeNotifier { final video = session.active is VideoPlayerPort ? session.active as VideoPlayerPort : null; + if (state == AppLifecycleState.inactive) { + debugPrint( + 'pip: inactive gate pageActive=$pipPageActive ' + 'video=${video != null} userWantsPlay=${session.userWantsPlay}', + ); + } if (state == AppLifecycleState.inactive && + pipPageActive && video != null && session.userWantsPlay) { debugPrint('pip: lifecycle inactive -> arm auto enter'); diff --git a/lib/pages/player/player_view.dart b/lib/pages/player/player_view.dart index 2144391..864221a 100644 --- a/lib/pages/player/player_view.dart +++ b/lib/pages/player/player_view.dart @@ -202,6 +202,7 @@ class _PlayerPageState extends State _pageController = logic.pages; // 自动小窗:独立播放页进入即挂;沉浸流随所在 tab 的激活状态挂/摘。 unawaited(logic.syncPipAutoArm(widget.embedded ? widget.active : true)); + logic.setPipPageActive(widget.embedded ? widget.active : true); if (!widget.embedded && !logic.isEpisodeLocked(logic.session.currentEpisode)) { _loadingVisible = true; @@ -222,6 +223,7 @@ class _PlayerPageState extends State // 沉浸流所在 tab 切换时同步自动小窗(激活挂、切走摘)。 if (widget.embedded && oldWidget.active != widget.active) { unawaited(logic.syncPipAutoArm(widget.active)); + logic.setPipPageActive(widget.active); } if (oldWidget.scrubCancelRequest != widget.scrubCancelRequest) { _cancelFeedScrub(); @@ -333,6 +335,7 @@ class _PlayerPageState extends State void dispose() { WidgetsBinding.instance.removeObserver(this); appRouteObserver.unsubscribe(this); + logic.setPipPageActive(false); _heartOverlayController.dispose(); _spriteAxisService ..removeListener(_handleSpriteFrameChanged)