From df2654c9d6582152ea102b853efcfcdb413cf561 Mon Sep 17 00:00:00 2001 From: Vicky <10212746+haifeng-jiang@user.noreply.gitee.com> Date: Wed, 28 Oct 2026 17:14:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(player):=20iOS=E8=87=AA=E5=8A=A8=E5=B0=8F?= =?UTF-8?q?=E7=AA=97=E4=BB=85=E5=9C=A8=E6=92=AD=E6=94=BE=E9=A1=B5=E6=B4=BB?= =?UTF-8?q?=E8=B7=83=E6=97=B6=E6=8B=89=E8=B5=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/player/player_logic.dart | 30 ++++++++++++++++++++++++++++++ lib/pages/player/player_view.dart | 3 +++ 2 files changed, 33 insertions(+) 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)