Clawline — 03-25~27 PWA适配与UX重构¶
移动端体验专项优化(03-25)¶
Dad 的目标¶
- 不需要放大
- 聊天界面不要横向滚动
- 尽量接近原生体验
Bot 的技术分析¶
- viewport 缺少
maximum-scale=1.0, user-scalable=no - Markdown 内容、代码块、长链接可能撑破布局
- 消息行与内容容器存在 overflow 风险
- 输入区按钮触控面积不足 44px
系统性修复方案¶
- 全局防 horizontal overflow:确保页面不会左右滚动
- 代码块内部滚动:代码块自己滚,不带动整页横向滚
- 长 URL 自动换行:避免长链接撑破布局
- 输入区按钮增大 touch target:满足 44px 最小触控目标
- iOS 风格滚动与
overscroll-behavior:提供原生般的滚动体验
结果:移动端横向滚动与误触问题得到系统性修复。
PWA Service Worker 缓存问题暴露与解决¶
问题现象¶
PWA 底部空白 / safe-area 问题修复后,用户仍看不到变化。
根因分析演进¶
第一次误判:Bot 怀疑 Tailwind arbitrary value 未编译,但检查后 CSS 已生成。
真正根因: - PWA Service Worker cache-first 导致用户仍在使用旧 JS/CSS - Dad 没看到更新提示,旧 SW 持续控制页面 - 这不是部署问题,而是 SW 缓存策略问题
解决方案¶
- 重新 build 生成新 hash
- SW 自动
skipWaiting()强制更新 - 在 Profile 页面加入版本号与 build hash,便于确认真机是否拿到新版本
- 通过 Vite define 注入全局版本信息
关键经验¶
PWA 缓存问题是"用户看不到更新"的常见根因,需要: 1. 明确的版本展示机制 2. 可靠的 SW 更新策略 3. 统一的 build hash 注入
PWA 层级问题修复¶
问题现象¶
ActionSheet 渲染在 overflow-y-auto 的消息容器内部,导致 iOS Safari/PWA 下 fixed 元素行为异常。
根因分析¶
- 不是单纯 z-index 数值不够
- 而是渲染层级上下文错误
- 输入栏与 slash menu 形成多个 stacking context
解决方案¶
- 将 safe-area 从 padding 改为独立 spacer,减少视觉空白
- 调整输入栏与 ActionSheet 的层级关系
- 将 ActionSheet 从滚动容器语义上"解耦"
关键提交:2e70ded2
大分支合并(03-26)¶
feat/sprint1-ux → dev 合并¶
分叉点问题:feat/sprint1-ux 从较早节点 4d1be4dc 分叉,早于后续 UI 改动,merge 时出现"旧 UI 覆盖新 UI"的风险。
冲突处理策略:
- MarkdownRenderer.tsx:采用 sprint1-ux 版本(包含 remarkGfm、rehypeRaw)
- ChatList.tsx:保留 sprint1-ux 功能,改回 dev 的固定列数 grid 方案
- ChatRoom.tsx:手工 patch 合并两边的改动
结果:build 成功,但 ChatRoom bundle 从 150KB 涨到 336KB。
UI 回退问题修复¶
Dad 发现:"气泡样式又回来了"
根因:旧分支 merge 时覆盖了后续 flat UI
处理:重新核对分叉点,修复后部署。提交:730608da
左右互搏式 UX 重构(03-27)¶
引入 adversarial-qa 三角色机制¶
Dad 决策:加入批判员(Critic),形成更严格的审查闭环。
最终角色:执行官、审核员、批判员
5 轮 ChatRoom 重构成果¶
关键成果:
- 提取/拆分:MessageItem、HistoryDrawer、HeaderMenu、LongPressActionSheet、chat/types/utils/constants
- ChatRoom.tsx 从 2619 行降到 1879 行(-28.3%)
- 终审评分 96/100 PASS
性能优化决策:
- 减少 motion.div 使用,消息行改普通 div + CSS transition
- 原因:长对话中每条消息一个 motion 实例,性能成本高
长按与复制功能修复¶
Dad 反馈:长按难用,复制文字功能"没法用了"
根因分析:
1. 移动端长按 400ms 就弹 ActionSheet,抢占了系统文字选择
2. 没有 touchmove 检测,想选中文字时被误判成长按菜单
3. navigator.clipboard 不存在时没有 fallback
4. copy 成功反馈只体现在桌面 hover 按钮上
解决方案:
- 在消息内容区域阻止 touchStart 冒泡
- 增加 copy toast
- 提高 ActionSheet 层级到 z-[60]
- 触发 ActionSheet 时清除系统选择
iOS 特有问题¶
- ActionSheet 与系统选择菜单同时出现
- ActionSheet 被底部输入栏遮挡
- Service Worker cache-first + iOS PWA 更新延迟
最终方案:SW 自动 skipWaiting(),统一 build hash 注入。
关键结论¶
这类问题的复合性¶
不是单纯前端样式 bug,而是 PWA 缓存策略 + iOS WebKit 行为 + DOM 层级结构 的复合问题。
组件拆分的价值¶
- 代码可维护性显著提升
- 单文件从 2600+ 行降到 1900 行
- 清晰的职责划分便于后续迭代
移动端体验的系统性思考¶
移动端优化不是"修几个 CSS",需要从: - viewport 配置 - 触控目标尺寸 - 滚动行为 - 长按/选择交互 - PWA 缓存策略 等多个维度系统性考虑。