001project_wildgrowth/ios/WildGrowth/COMPLETION_迭代_审查报告.md

5.1 KiB
Raw Blame History

完成页迭代方案 — 审查报告(禁止应用)

审查对象:左滑进完成页、右滑回最后一节;无顶部返回;无打字机金句;底部「回到我的内容」回到技能页 Tab。
结论:只做审查与完整代码输出,不修改仓库文件。


一、需求与方案对照

需求 方案 审查结论
不想要点开页面导航栏的返回按钮 移除顶部导航栏和返回按钮,仅顶部留白 一致
右滑回到最后一个小节 .enableSwipeBack() + SwipeBackEnabler 强制开启侧滑返回 ⚠️ 见下文「侧滑返回」
最后小节左滑进完成页,右滑回最后小节 播放器最后一节挂 LastPageSwipeModifier 左滑 push完成页右滑 = 系统 pop 一致
不要打字机金句 移除打字机区域 一致
底部「回到我的内容」回到技能页 Tab 方案写的是 navigationPath = NavigationPath() 逻辑错误,见下

二、关键问题:底部按钮语义

需求:底部「回到我的内容」要回到技能页 Tab(即技能 Tab 根:课程列表)。

方案中的实现handleReturnToRoot() 里写的是 navigationPath = NavigationPath(),即清空当前传入的 path

  • 若从技能 Tab进入:传的是 growthPath,清空后 = 技能 Tab 根
  • 若从发现 Tab进入:传的是 homePath,清空后 = 发现 Tab 根,不会切到技能 Tab
  • 若从我的 Tab进入:传的是 profilePath,清空后 = 我的 Tab 根,不会切到技能 Tab

因此:仅清空当前 path 无法满足「无论从哪个 Tab 进,都回到技能页 Tab」

正确做法:底部按钮应调用 navStore.switchToGrowthTab()(切到技能 Tab + 清空 growthPath),与当前线上 CompletionView 的「继续学习」一致。

  • CompletionView 需保留 @EnvironmentObject var navStore
  • 不需要为「回到我的内容」传入 @Binding var navigationPath(调用方无需改传参)

完整代码中已按此修正:底部按钮调用 navStore.switchToGrowthTab(),不传 navigationPath


三、侧滑返回SwipeBackEnabler

  • 方案用 SwipeBackEnablerUIViewControllerRepresentable)在 .background 里查找 navigationController 并打开 interactivePopGestureRecognizer,以在隐藏导航栏时恢复右滑返回。
  • 风险makeUIViewController 返回的是一颗裸 UIViewController(),其 navigationController 在部分时机可能仍为 nil例如尚未挂到 NavigationStack 上),DispatchQueue.main.async 能缓解但无法完全保证。若遇真机偶发无效,可考虑:
    • updateUIViewController 中轮询/延迟再取一次 navigationController,或
    • 使用 UINavigationController 子类 / 注入方式保证拿到的必为当前栈。
  • 结论:实现可保留,建议在真机多场景(从三个 Tab 进入完成页后右滑)验证;若失效再加强时机或注入方式。

四、VerticalScreenPlayerView 与占位页

  • 方案采用「不使用占位页,仅最后一节左滑手势 push 完成页」TabView 只渲染 ForEach(allCourseNodes),不再多一页 CompletionPlaceholderPage
  • 影响
    • 进入完成页仅剩「在最后一节左滑」这一种方式;「滑到下一空白页再进完成页」的路径被移除。
    • 从完成页右滑或 dismiss 后,播放器不再存在「当前是占位页、需在 onAppear 里切回最后一节」的状态,可删除 onAppear 里对 currentNodeId == "wg://completion" 的处理。
  • 与现有调用方NoteTreeView / NoteListView 不传 navigationPathtriggerCompletionNavigation 里需 guard let path = navigationPath else { return },从笔记进的播放器仍不会 push 完成页,行为不变。

五、CompletionView 视觉与接口

  • 视觉:从当前 3D 翻转卡片 + 打字机,改为「赛博印章」:圆环 + 未盖章「完」/ 盖章后「已完成的第 N 节」+ 底部「回到我的内容」。
  • 接口
    • 保留:courseId, courseTitle, completedLessonCount
    • 不增加 @Binding var navigationPath(底部用 navStore.switchToGrowthTab())。
    • 保留 @EnvironmentObject var navStore
  • 调用方GrowthView / ProfileView / DiscoveryView 的 .completion 分支无需新增参数,仍为三参构造。

六、审查结论汇总

结论
顶部去掉返回按钮 方案正确
右滑回最后一节 思路正确SwipeBackEnabler 需真机验证,偶发需加强时机
最后小节左滑进完成页 保留 LastPageSwipeModifier 即可
去掉打字机金句 方案正确
底部回到技能页 Tab 方案用「清空当前 path」会错应用 navStore.switchToGrowthTab(),完整代码已改
调用方改动 CompletionView 不需新参数VerticalScreenPlayerView 保持可选 navigationPath,笔记流不受影响

完整代码见下(仅作交付,不写入仓库)。