Skip to content

fix(app): #85 dark mode 全屏巡检 —— ScreenTour 截图基建 + 四处 UI 修复 + emoji 稳定映射 - #92

Merged
sweetcornna merged 1 commit into
mainfrom
polish/dark-sweep-85
Jul 26, 2026
Merged

fix(app): #85 dark mode 全屏巡检 —— ScreenTour 截图基建 + 四处 UI 修复 + emoji 稳定映射#92
sweetcornna merged 1 commit into
mainfrom
polish/dark-sweep-85

Conversation

@sweetcornna

Copy link
Copy Markdown
Owner

概要

落实 #85(13 屏 dark mode 目视验收)。本环境跑不了 XCUITest,所以先建了一套屏幕巡检基建:DEBUG 启动参数直达任意一屏 + simctl 逐屏截图,验收变成可重复执行的脚本。

巡检基建

  • DevTools/ScreenTour.swift-uiTourScreen <screen> 直达 19 屏(13 屏清单全覆盖 + onboarding/catalog 等),内存容器 + DevSampleData 种子 + Fake 服务,不弹权限窗
  • scripts/tour-shots.sh:一键逐屏截图(--appearance dark|light),统一状态栏;产物在 design/tour-shots/(已 gitignore)
  • voxuleApp:生产容器抽成 makeProductionContainer();巡检分支切内存种子容器 + Fake 音频/圈服务

巡检发现并修复(dark 19 屏 + light 抽查 6 屏,逐张目视)

问题 修复
浮现卡 朱红批注与卡片标题重叠 批注上移 lg 骑在卡顶边,半出半进
圈列表 行尾双 chevron(自绘+系统) 删自绘,统一走系统 disclosure
胶囊详情 空/坏音频进页即弹 alert 改播放卡 inline 批注「这段声音没能读出来。」
关于 八色 swatch 钉死 light 端,暗房里发亮 adaptivePalette 跟随翻面

其余屏 dark 形态全部通过:暗房不变浅、PhotoCard 图像区恒黑、朱红/朱章稳定、玻璃 chrome 薄釉可见、DesignCatalog 翻面对照两栏 swatch 明显不同。

emoji 稳定映射(§11.1 低优先级项 + 巡检实证)

String.hashValue 每次进程随机加种 —— 巡检两次冷启动「家」的头像从 👨‍👩‍👧 漂到 🌿,「同名稳定」从未成立。新增 CircleEmoji(FNV-1a 稳定 hash),列表/详情/建圈三处重复实现收敛一处,圈池 10→24、成员池 12→22;CircleEmojiTests 固定向量钉死算法。

附带

  • DevSampleData 音频从留空改为程序生成 1.6s 正弦 WAV(无文件依赖),种子胶囊可真回放,Dev 工具 footer 同步改口
  • run-sim.sh UDID 提取 POSIX 化已随 main 直提(c8c2d09)

回归

  • swift test 141 通过;build-for-testing SUCCEEDED(app 侧测试本环境跑不了,CI/开发机可跑)
  • scripts/check-clinical-words.sh 无命中(下方自检)
  • 巡检截图复核:修复四屏 dark+light 双形态重截确认

验收状态(#85

模拟器侧 13 屏(实际 19 屏)dark 验收完成;issue 里「真机」一项如需补充可在真机重跑 scripts/tour-shots.sh 同清单目视。

巡检基建(无 XCUITest 环境的目视验收方案):
- DevTools/ScreenTour.swift:DEBUG 启动参数 -uiTourScreen 直达 19 屏,
  内存容器 + DevSampleData 种子 + 全套 Fake 服务,不弹权限窗
- scripts/tour-shots.sh:simctl 逐屏截图(dark/light),统一状态栏
- voxuleApp:生产容器抽 makeProductionContainer(),巡检分支换内存种子容器

巡检发现并修复:
- SurfacedCapsuleView:MarginNote 批注上移骑卡顶边,不再压标题
- CircleListView:删自绘 chevron(与系统 disclosure 双箭头)
- CapsuleDetailView:空/坏音频不再进页即弹 alert,改播放卡 inline 批注
- AboutView:八色 swatch 误用固定 light 端 palette,改 adaptivePalette 跟随翻面
- DevSampleData:音频从留空改为程序生成 1.6s 正弦 WAV,详情/浮现卡可真回放

emoji 稳定映射(§11.1 低优先级 + 巡检实证的重启漂移 bug):
- 新增 CircleEmoji:FNV-1a 稳定 hash 取代 String.hashValue(每进程随机加种,
  「同名稳定」从未成立),三处重复实现收敛一处,圈池 10→24、成员池 12→22
- CircleEmojiTests:固定向量钉死算法 + 空名 fallback + 落点在池内

回归:swift test 141 通过;run-sim.sh --build-only 与 build-for-testing 均 SUCCEEDED;
dark 19 屏 + light 抽查 6 屏截图目视复核通过。
@sweetcornna
sweetcornna merged commit 530b543 into main Jul 26, 2026
1 check failed
@sweetcornna
sweetcornna deleted the polish/dark-sweep-85 branch July 26, 2026 15:12

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

https://github.com/sweetcornna/voxule/blob/d0ec65051025e7bfd3f8c8631f71c82351e318e8/voxule/Features/Circle/CircleEmoji.swift#L44
P2 Badge Normalize names before hashing their UTF-8

When a circle or member name arrives in a canonically equivalent Unicode form, this hashes different bytes even though Swift considers the strings equal. For example, "é" and "e\u{301}" select circle-pool indexes 1 and 7 respectively, so names entered by different keyboards or synced from another device can still display different avatars. Normalize the trimmed name to a canonical form before applying FNV-1a so the new cross-device stability guarantee holds.


https://github.com/sweetcornna/voxule/blob/d0ec65051025e7bfd3f8c8631f71c82351e318e8/voxule/voxuleApp.swift#L111-L113
P2 Badge Reuse the seeded circles in tour mode

When launching -uiTourScreen circles, ServiceContainer.preview() creates two new circles with fresh UUIDs and no members, while ScreenTour.makeSeededContainer() assigns capsules and members to a different pair of circles. Consequently, CircleListView always renders 0 位成员 and latestTitle(forCircle:) never finds a matching capsule, so this tour target cannot visually inspect the populated member counts or recent-capsule row it is intended to cover. Initialize the fake service from the seeded container's circles, or otherwise keep their IDs and relationships aligned.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant