跳转至

PR #58 审查:OneGUI 玻璃、OH/标签页与学习功能

审查日期:2026-10-26。PR:smartThise/OneTHU#58,作者 xiao-dreamr。

  • 基线:ab0899f684abdc0201cdc64728e1e6e6281dad80。
  • 审查版本:08b1caa4ebede7e12f810b48d76e2bd6f7d7bb72。
  • 范围:100 个文件,4909 行新增、466 行删除;涵盖视觉、认证恢复、原生下载、雨课堂/TUOJ、壁纸与国际化。

结论:建议修复以下 5 处后再合并。材质按 OneGUI 管线统一、标签页重排动效等方向可以保留;目前的阻断来自具体校验、能力识别、生命周期和持久化问题。

1. [P1] 按 MIME 补后缀绕过附件登录页检查

位置:apps/desktop/src-tauri/src/lib.rs:1102。

ensure_extension 在登录页检查之前,根据响应 Content-Type 给文件名补后缀。附件名缺少扩展名、会话过期且学校返回 HTTP 200 HTML 登录页时,text/html 会把原来的 下载 改成 下载.html。随后的 name_is_html 变为 true,整个 HTML/重定向校验被跳过;下载以成功返回,保存的是登录页。

复现使用 PR 中实际 Rust helper 编译执行,结果为 filename=下载.html、htmlValidationRuns=false。这是原有拒绝路径变成成功路径的回归。应先基于原始显式文件名、响应地址和认证页面特征完成验证,再补推断后缀;推断出来的 .html 不能作为“原本就是合法 HTML 附件”的证据。

2. [P2] 折射功能使用被伪装的 UA 判断真实内核

位置:packages/gui/src/pipeline/refraction.ts:65。

范围澄清:此项只涉及新增的 SVG 边缘折射增强。PR 对普通 CSS 背景模糊、透明材质、阅读面和暗色对比度的修复不经过这道门禁,在 Windows App 中可以正常改善视觉。用户补充作者在 Windows 测试过玻璃修复,本条不否定该实测,也不能据此概括为“Windows 上玻璃修复无效”。

能力判断最终要求 navigator.userAgent 中的 Chromium 版本至少为 96;应用的 tauri.conf.json:23 为学校认证兼容固定使用 Chrome/79.0.3945.88。因此即使 Windows WebView2/Android 的实际内核支持 SVG backdrop filter,也会返回 false,生产 App 无法进入这条新折射管线。macOS 的 WebKit 降级则是实现明确设定的范围。

纯函数复现:使用配置中的 UA,并令两项 SVG/CSS 能力探测为 true,返回值仍为 false。需要使用真实能力或宿主提供的真实内核信息判断,保留既有学校请求 UA。

仓库中的 home-shell-appearance-browser-test.mjs 明确声明使用 Chromium 与 Windows platform hint,未宣称原生 WebView2 验收;glass-optics-test.mjs 的现代分支使用浏览器默认 UA,旧内核分支使用 Chrome/90 UA。这些自动化用例没有覆盖主窗口固定 Chrome/79 的组合,作者额外进行的 Windows 手测仍作为独立证据看待。

3. [P2] 折射节点移除后不释放,24 个候选名额永久耗尽

位置:packages/gui/src/pipeline/refraction.ts:356。

MutationObserver 只处理 addedNodes,未处理被移除节点;update() 仅过滤 isConnected,不从 lenses 删除记录,也未调用已经定义的 forget()。discover() 又以 lenses.size >= 24 拒绝新候选。临时面板开关、标签页关闭等操作会逐步耗尽名额,并保留已卸载 DOM、观察器和滤镜引用。

已在隔离的真实无头 Chrome 中加载 PR 的实际模块,逐个挂载并移除 24 个 .lens:前 24 个均成功获得折射,第 25 个仍在视口、材质和尺寸符合要求,却不再获得折射。应在发现新节点之前清理断开连接的 lens,并释放对应观察器和 filter。

4. [P2] 新增日夜壁纸设置经过云端存档恢复会丢失

位置:apps/desktop/src/state/wallpArchive.ts:97。

PR 将运行态 WallpaperDoc 升为 v3 并新增 day、night,但导出格式不保存这两个字段,导入又显式将两者置为 null。wallpsync.ts 正是通过这两个函数进行云端上传和恢复,因此新增设置在同步恢复/换机后被清空。

实际调用导出→导入的结果:day=builtin:aurora, night=builtin:dusk 变为两者均 null。应在存档中携带和验证这两个引用,将其媒体计入资源和大小预算,同时兼容没有这两个字段的旧存档。

5. [P2] 新增 18 个翻译键未登记到生成源,handoff 全部删除

位置:apps/desktop/src/i18n/locales/zh-CN.ts:6497,以及对应英文词典。

PR 直接添加语言文件,却未更新 i18n seed/提取源。这次新增的 18 个键,包括试卷、进行中、新标签页打开、日夜背景和设置导航说明,在隔离快照运行 tools/i18n/build-handoff.mjs 后全部消失。生成前 i18n:check 为 errors 0,也无法证明下一轮生成可保留它们。

应将新增键和改名文案同步登记到 docs/i18n/static-label-seed.json 等对应源,重新生成批次,再检查和比较生成前后的键集合。只保留手改语言文件会使后续正常翻译流程引入缺键。

验证与边界

  • 在 /tmp/onethu-pr58-review-08b1caa4 提取 PR 快照执行,未切换当前工作分支,也未启动或重启用户 OneTHU。
  • PR 附件名测试 8 条通过;外部作业状态测试 346 条通过;雨课堂正文测试 164 条通过。
  • 原生下载校验使用抽取的实际 Rust helper 和对应分支条件复现,未构建/安装整个 App,也未请求真实学校附件。
  • 折射候选耗尽使用实际 Chrome、PR 模块和合成 DOM 复现;没有使用用户浏览器资料或学校数据。
  • 日夜壁纸用真实存档函数和内置壁纸引用完成往返复现。
  • i18n 生成前检查通过;隔离快照执行生成器后确认新增 18 键全部丢失。未改工作区词典。
  • GitHub 该 head 没有检查记录;PR 正文中的构建/浏览器检查为作者自报,本次未完整重跑全部三端构建及视觉测试。

与当前未提交开发的合并注意事项

GitHub 的已提交 main 基线可合并。当前本机还有统一 CLI/后台及通知附件名等未提交开发,git apply --check 已确认 PR 在中英词典和 packages/core/src/learn/client.ts 上不能直接应用。

附件名方案应合并:保留 PR 的属性/URL 名称解析思路,同时保留本地刚修复的通知列表 fjmc 回填和 GUI/SDK 传递链路。只用 PR 的附件名推导仍不能保证恢复“名称仅存在于列表字段”的通知附件。

本轮只记录审查;没有修改 PR、提交远端评论、合并或推送。