Repository navigation
fix: retain iOS overlay window during interactive dismissal - #263
Conversation
|
@codex review |
|
@codex security review |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Cursor review failed. Remote error: |
|
Skipping Bugbot: Bugbot is disabled for this repository. Visit the Bugbot dashboard to update your settings. |
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
PR #263 代码审查报告审查概要
运行时拓扑与复现/验收条件核对
评分
发现的问题本次变更未发现 [P2] [🟠 Medium]
|
| 优先级 | 置信度 | 文件 | 类型 | 描述 | Auto-fix |
|---|---|---|---|---|---|
| P2 | 🟠 Medium | NativeOverlayWindowManager.swift:354-363 |
运行时 | interactiveCoordinator(in:) 遍历 children 以覆盖子导航栈侧滑返回等交互转场 |
✅ |
| P2 | ⚪ Low | NativeListMediaVisibilityTests.swift:60-112 |
规范 | 将 slot.recycle() / second.recycle() 移入 defer 确保断言失败时也能清理 |
✅ |
测试建议
- iOS 真机手势回归: 在 iOS 真机(120Hz ProMotion 设备)上复测「关闭
NativeOverlaySheet(如 More)后0.1s–0.3s内立即下拉底层系统 Sheet(如账户选择器)或执行页面侧滑返回」,确认真机 BackBoard 事件分派下无悬停卡顿。 - 连续快速重开同一 Overlay: 在底层 Sheet 处于交互式下拉过程中,快速触发同一
NativeOverlay(或 Toast)关闭再打开,验证新窗口可正常交互且旧窗口在手势结束后正常释放。 - iPad 多窗口 / Stage Manager 场景: 在 iPad 分屏或关闭窗口触发
UIScene.didDisconnectNotification时,确认处于retiredWindows状态的窗口被干净回收且无崩溃。
问题与复现
iOS 账户选择器与右上角 More 是两个不同的窗口层:账户选择器由 App 主窗口承载,More 由 NativeOverlay 的独立
UIWindow承载。在 iOS 27.0 模拟器、三账户测试钱包中:修复前,同一短间隔轨迹在两次干净 App 运行中均使账户选择器停在约下移 171 pt 的位置;UIKit
transitionCoordinator仍为isInteractive = YES、percentComplete ≈ 20.94%。再次下拉后可停在约 57.3%,无法正常关闭。只把 More 结束到后层开始的间隔改为 1.25 秒,后层则正常退出(1/1)。JS 路由查询在悬停时仍响应,因此这里不把现象描述为整个 App 主线程死锁。原因分析
旧实现收到 More entry 移除时立即隐藏并释放它的窗口、root controller 和 scene context,按既有规则处理 key window 归还。短间隔下,UIKit 已将后层触摸的前 7 个
UIEvent送往主窗口,但它们仍带旧 overlay context 标记;旧窗口 context 被注销后,同一段输入的后续 29 个事件未还原为UIEvent,日志改为直接分派 backing event。这与交互转场悬停的时间线一致。UIKit 日志未直接给出 pan recognizer 的 ended/cancelled phase,因此不能据此断言系统已明确丢弃 UP,也不能将模拟器证据直接归因为用户真机的唯一原因。另做了只在测试进程内将
resignKey()调用refreshReactNativeDimensions()的指令临时替换为 NOP 的诊断对照;同一短间隔轨迹仍悬停。这只排除该 helper 调用对本次复现的必要性,未改磁盘依赖或源码,并已通过重启恢复原指令。修复
notifyWhenInteractionChanges,在交互结束或取消后下一次 main turn 重新检查当前 coordinator;若又进入交互,则继续等待。按退休窗口身份幂等清理,旧回调不会释放同一 owner 重开的新窗口。目标平台是 iOS 的
mainUI。窗口管理器是进程内、主线程使用的 UIKit 资源;iOSbg有独立 JS heap 和初始化时序,本案没有bg参与证据,也没有数据反序列化路径变更。验证
tests/ios/run.sh:11/11 通过。新增的 4 个用受控 transition coordinator 验证 manager 的完成、取消与重入、同 owner 重开、scene disconnect 生命周期;它们不代替真实手势验证。UIEvent均送到主窗口,最后事件后约 27 ms 才完成旧窗口 context 清理。录屏
以下均为 iOS 27.0 模拟器、三账户测试钱包的原始实测录像。
修复前:完整复现
More 多次往返、部分下拉松手自行回弹,再关闭 More 并紧接着拖后层,账户选择器停在中段。
multi-wiggle-half-rebound-case1.mp4
修复前:继续下拉仍无法关闭
在同一异常现场继续下拉,松手后仍停在半路。
multi-wiggle-half-rebound-case1-retry-drag.mp4
修复后:相同短间隔轨迹正常关闭
保持 More 结束到后层开始的 0.25 秒输入间隔,账户选择器正常关闭至 Home。
owner-fix-short1.mp4
修复后:部分下拉松手自动回弹
后层低速部分下拉后松手,账户选择器自行回到原位。
owner-fix-short-cancel-retry2-valid.mp4
验证边界
验证范围仅为 iOS 27.0 模拟器及上述局部手势;真机、iPad 与更广运行矩阵尚未验证。此 SDK 源码修复还需要后续 SDK 与 App 原生发版才能进入用户安装包;本 PR 不发包。
CI 跟进
原
ios-native作业失败于 NativeList 的testVisibleVideoReleasesPlayerAfterCapturingFirstFrame:截止时加载回调与首帧仍为空;ios-xctest因上游失败连带失败。该测试没有调用本次修改的 overlay 窗口管理器。提交
364ff1735仅修正现有 XCTest 夹具:将两个视频预览挂到 AppHost 已显示窗口中的临时容器,绑定前检查窗口归属和视口,退出时移除容器。保留原首帧成功、64×48 尺寸、播放器释放和缓存复用断言,以及原 10/3/3 秒截止时间;没有修改 NativeList 业务代码。日志不足以断言 key 状态就是旧失败的唯一原因。364ff1735的当前 15 项 GitHub checks 全部通过,包括ios-native、ios-xctest和device-utils-store。Hosted iOS 作业 中,此前失败的首帧用例通过(1.794 秒);NativeList 套件共 88 项、1 项既有跳过、0 失败。