聊天侧边栏体验优化

Link copied!

去 Modal + Reanimated 动画、NoSQL 会话读写、确认流图拓扑、SSE payload 补丁等 11 个子问题

于成季 by 于成季 ·

1. 问题背景

神秘人 agent-chat 页通过右上角图标打开历史会话侧栏(列表 + 遮罩)。联调与真机反馈:打开/关闭不跟手、偶有顿挫,与主对话区的流畅度不一致;期望侧栏动画稳定 60fps、交互反馈明确。

2. 问题列表

2.1 打开侧栏瞬间卡顿、动画不平滑

根因:侧栏曾被包在 Modaltransparent + animationType="none")里;每次 visible=true 会走原生 Modal 挂载/层级切换,与后续 Animated + requestAnimationFrame 拼出来的打开动画叠在一起,主线程调度成本高。

采纳方案:去掉 Modal,在同屏内用 StyleSheet.absoluteFill + 高 zIndex/elevation 做全屏层;动画改由 react-native-reanimateduseSharedValue + withSpring/withTiming 驱动(UI 线程路径)。独立组件 AgentChatHistoryDrawer + 动画参数 drawerTokens.ts

2.2 关闭路径不一致、部分操作「瞬关」无动画

根因:历史代码里 closeSidebar 仅存 setState,未与带动画的 dismissDrawer 统一。切换会话 / 新建会话若直接 setSidebarOpen(false),侧栏瞬时消失。

采纳方案:侧栏 closed / opening / open / closing 状态机(useReducer),禁止页面内再写 setSidebarOpen;关栏统一 requestClose()CLOSE_START → 动画结束 → CLOSED

2.3 历史列表首开展示时掉帧

根因:会话较多时,第一次打开侧栏 FlatList 布局+挂载与动画同帧竞争。

采纳方案:listAgentChatSessionsPage(常量 AGENT_CHAT_SESSION_PAGE_SIZE)+ 触底 onEndReached 追加;列表为 @shopify/flash-list;首屏同步前骨架屏。

2.4 拖动手势关栏与列表滚动抢事件

根因:若 Pan 包在整个侧栏面板外,纵向滑列表易与横向关栏手势冲突;FlatList 内部滚动与父级 Gesture.Pan 默认未声明同时识别关系。

采纳方案:仅「历史记录」标题栏包一层 GestureDetectorPan.activeOffsetX / failOffsetY 约束激活条件;列表外包 NativeViewGestureHandler 并与 Pan simultaneousWithExternalGesture(ref)。Web 暂不启用手势(避免与浏览器滚动差异),仍依赖点遮罩/按钮。

2.5 Android 物理返回与 Modal 语义丢失

根因:移除 Modal 后,系统不再自动把返回键关联到 onRequestClose。表现为侧栏打开时按返回直接退出页面。

采纳方案:sidebarOpen 为真时注册 BackHandler,消费事件并调用 dismissDrawer()

2.6 打开时缺少触感反馈

根因:纯反馈弱,用户心理模型上「打开抽屉」常与轻触感搭配。

采纳方案:openSidebar 内(非 Web)Haptics.impactAsync(Light)

3. 小结

← 所有文章