AGC 会话区:移除「显示更早的对话」按钮,需要时自动加载更早历史 #510

Closed
opened 2026-09-24 15:16:26 +08:00 by suzmii · 1 comment
Member

现象

AGC 会话区顶部常驻一颗「显示更早的对话」按钮(见附图)。用户要看到更早的回合只能手动点,而滚动到顶部其实已经会触发同一件事——同一入口两种语义。hasMore 为真时按钮一律显示,用户无法从按钮本身判断"是只差一两条"还是"这一屏根本没装满"。

诉求:去掉这个按钮,改成"需要加载时自动加载"。

问题原因(代码事实)

DirectProject 项目对话面板(截图里那个「已打开:…」页面)

# 位置 事实
1 chat/components/DirectProjectConversation/DirectProjectConversation.tsx:43-51 historyHasMore 为真就渲染 button.message-history-more,文案固定「显示更早的对话」
2 chat/DirectProjectChatView.tsx:228-232 自动取页只挂在 onScroll 上:if (historyHasMore && list.scrollTop <= 24) void loadEarlierHistory()
3 src/styles.css:2701-2704、:9251-9254 会话列表 min-height: 340px;工作台内 height: 100%; min-height: 96px。首屏切片渲染不满容器时 scrollTop 恒为 0,永远不会产生 scroll 事件 → 自动入口整条失效,按钮成了唯一入口
4 chat/controller/useDirectProjectChatController.ts:745-789 loadEarlierHistory 自带 historyHasMore / historyLoadingRef 双闸;readDirectHistoryPages 单次最多 5 页(DIRECT_HISTORY_MAX_PAGES_PER_ACTION),停止判据是"合并后回合数增加"
5 chat/history/directHistoryPaging.ts:8、docs/project-memory/shared-memory/decision-log.md:596-601 明确记过"不新增 loading / 禁用态与新文案,不做滚动锚定补偿"。取页内容并到列表顶部时 scrollTop 数值不变,视野被推向更早内容——贴顶用户会被持续"拽走"

立项策划面板(PlanningChatView,同类按钮)

# 位置 事实
6 planning/PlanningChatView.tsx:269-279 hiddenConversationCount > 0 || hasEarlierConversationMessages 时渲染同一个 button.message-history-more,文案「显示更早 · 还有 N 条对话」/「显示更早的对话」
7 src/App.tsx:2077-2095 真相是前端窗口 conversationVisibleCount + latestVisibleItems(messages, n);showEarlierConversationMessages 只是 +CONVERSATION_VISIBLE_STEP(纯同步,无在途态)
8 src/App.tsx:2092-2094 自动入口同样是"只挂 scroll":scrollTop <= 24 才加一屏 → 上表 #3 的零 scroll 事件场景同样存在

两处都只是"把更早的内容从上面补进来",机制不同(后端切片 vs 前端窗口),但入口语义与缺口一致。

打算怎么改(方案)

  1. 删除两处按钮:
    • DirectProjectConversation 移除 button.message-history-more 分支与 onLoadEarlierHistory prop,DirectProjectChatView 停止传参;
    • PlanningChatView 移除按钮分支与 onShowEarlierMessages prop,App.tsx:2220 停止传参;
    • src/styles.css:5015 删掉 .message-history-more 规则;:9408 的 .message-action, .message-history-more 组合选择器只摘掉后半段(.message-action 仍在用)。
  2. 统一自动触发判据(每条链路各一份实现,别在调用点散写):
    • 贴顶:沿用 scrollTop <= 阈值,把硬编码的 24 收敛到常量(现有 AGENT_CHAT_SCROLL_BOTTOM_THRESHOLD = 48 用于"贴底"判定,取页阈值要独立命名,避免两个语义共用一个数字);
    • 未填满:scrollHeight <= clientHeight + 阈值 视为"必须加载"。在挂载后、每次合并历史后、容器尺寸变化(ResizeObserver)后各判一次;hasMore 为真就继续取,直到列表可滚动或 hasMore=false;
    • 两条入口都走同一个加载函数,Direct 侧保留 historyLoadingRef 并发闸与单次 5 页上限;策划侧是同步加一屏,天然无并发,但要保留"一次操作最多 5 步"与"到顶即停"的边界。
  3. 补上滚动锚定补偿:取页前后记 scrollHeight,合并后 scrollTop += 新 scrollHeight − 旧 scrollHeight,保持用户当前可视内容不动。这同时掐掉"贴顶 → 自动取页 → 视野被推向更早内容 → scroll 事件递归触发 → 一路拉到整份历史"的连锁。补偿只在"取页前就贴顶或未填满"时做;用户主动滚回底部后不再自动取页(Direct 侧沿用 shouldFollowLatestRef 语义)。
  4. 同步既有约定文档(本次是有意变更既有口径,不是补漏实现):
    • docs/technical/【技术方案】DirectProject Codex原始历史与异常恢复-2026-09-04.md:95("必须显示『显示更早的对话』入口,并允许按钮或滚动触发");
    • docs/project-memory/plans/【里程碑】DirectProject Thread Manager事件订阅-2026-09-15.md:47;
    • docs/project-memory/shared-memory/decision-log.md:596-601(新增一条决策:入口由按钮改为自动加载 + 允许锚定补偿);
    • chat/history/directHistoryPaging.ts:8 注释里的「显示更早」措辞。
  5. 测试:
    • apps/ai-game-creator-shell/tests/directProjectProcessStatus.test.tsx:28-32,62-66 去掉 onLoadEarlierHistory;
    • planning 侧渲染用例去 onShowEarlierMessages;
    • 新增回归网两例:① 首屏不满一屏 + hasMore=true → 无任何点击自动出现更早回合;② 贴顶取页后可视首条不变(锚定补偿)。变异验证:把"未填满"判据与补偿分别去掉,两条用例各自变红。

范围

  • 会话区入口表现与自动加载时机:DirectProjectConversation / DirectProjectChatView / App.tsx 的策划链路 / styles.css / directHistoryPaging 注释与既有约定文档。
  • 不动后端切片契约(read_direct_project_history_slice 的 limit / beforeItemId / hasMore 语义)、historyLoadingRef 并发闸、5 页上限、失败保留已成功页的既有行为。

验收判据

  • 会话区不再出现「显示更早的对话」按钮(两个面板都不出现);rg message-history-more 只剩 .message-action 那条样式。
  • 首屏不满一屏且还有更早历史 → 无需任何操作,自动续拉直到可滚动或历史取尽。
  • 用户滚到顶部 → 自动取更早的回合,且可视内容不跳动(取页前后可视首条同一条消息)。
  • 一次操作最多 5 次请求的上限、hasMore=false 早停、单页失败保留已成功页、用户滚回底部后停止自动取页,行为全部不变。
  • npm run ai-game-creator-shell:typecheck、AGC 前端定向用例、npm run check:encoding、git diff --check 通过。

附

  • 触发场景截图见评论。
## 现象 AGC 会话区顶部常驻一颗「显示更早的对话」按钮(见附图)。用户要看到更早的回合只能手动点,而滚动到顶部其实已经会触发同一件事——同一入口两种语义。`hasMore` 为真时按钮一律显示,用户无法从按钮本身判断"是只差一两条"还是"这一屏根本没装满"。 诉求:**去掉这个按钮,改成"需要加载时自动加载"**。 ## 问题原因(代码事实) ### DirectProject 项目对话面板(截图里那个「已打开:…」页面) | # | 位置 | 事实 | |---|---|---| | 1 | `chat/components/DirectProjectConversation/DirectProjectConversation.tsx:43-51` | `historyHasMore` 为真就渲染 `button.message-history-more`,文案固定「显示更早的对话」 | | 2 | `chat/DirectProjectChatView.tsx:228-232` | 自动取页**只挂在 `onScroll` 上**:`if (historyHasMore && list.scrollTop <= 24) void loadEarlierHistory()` | | 3 | `src/styles.css:2701-2704`、`:9251-9254` | 会话列表 `min-height: 340px`;工作台内 `height: 100%; min-height: 96px`。首屏切片渲染不满容器时 `scrollTop` 恒为 0,**永远不会产生 scroll 事件** → 自动入口整条失效,按钮成了唯一入口 | | 4 | `chat/controller/useDirectProjectChatController.ts:745-789` | `loadEarlierHistory` 自带 `historyHasMore` / `historyLoadingRef` 双闸;`readDirectHistoryPages` 单次最多 5 页(`DIRECT_HISTORY_MAX_PAGES_PER_ACTION`),停止判据是"合并后回合数增加" | | 5 | `chat/history/directHistoryPaging.ts:8`、`docs/project-memory/shared-memory/decision-log.md:596-601` | 明确记过"不新增 loading / 禁用态与新文案,**不做滚动锚定补偿**"。取页内容并到列表顶部时 `scrollTop` 数值不变,视野被推向更早内容——贴顶用户会被持续"拽走" | ### 立项策划面板(`PlanningChatView`,同类按钮) | # | 位置 | 事实 | |---|---|---| | 6 | `planning/PlanningChatView.tsx:269-279` | `hiddenConversationCount > 0 \|\| hasEarlierConversationMessages` 时渲染同一个 `button.message-history-more`,文案「显示更早 · 还有 N 条对话」/「显示更早的对话」 | | 7 | `src/App.tsx:2077-2095` | 真相是前端窗口 `conversationVisibleCount` + `latestVisibleItems(messages, n)`;`showEarlierConversationMessages` 只是 `+CONVERSATION_VISIBLE_STEP`(纯同步,无在途态) | | 8 | `src/App.tsx:2092-2094` | 自动入口同样是"只挂 scroll":`scrollTop <= 24` 才加一屏 → 上表 #3 的零 scroll 事件场景同样存在 | 两处都只是"把更早的内容从上面补进来",机制不同(后端切片 vs 前端窗口),但**入口语义与缺口一致**。 ## 打算怎么改(方案) 1. **删除两处按钮**: - `DirectProjectConversation` 移除 `button.message-history-more` 分支与 `onLoadEarlierHistory` prop,`DirectProjectChatView` 停止传参; - `PlanningChatView` 移除按钮分支与 `onShowEarlierMessages` prop,`App.tsx:2220` 停止传参; - `src/styles.css:5015` 删掉 `.message-history-more` 规则;`:9408` 的 `.message-action, .message-history-more` 组合选择器**只摘掉后半段**(`.message-action` 仍在用)。 2. **统一自动触发判据**(每条链路各一份实现,别在调用点散写): - 贴顶:沿用 `scrollTop <= 阈值`,把硬编码的 `24` 收敛到常量(现有 `AGENT_CHAT_SCROLL_BOTTOM_THRESHOLD = 48` 用于"贴底"判定,取页阈值要独立命名,避免两个语义共用一个数字); - **未填满**:`scrollHeight <= clientHeight + 阈值` 视为"必须加载"。在挂载后、每次合并历史后、容器尺寸变化(`ResizeObserver`)后各判一次;`hasMore` 为真就继续取,直到列表可滚动或 `hasMore=false`; - 两条入口都走同一个加载函数,Direct 侧保留 `historyLoadingRef` 并发闸与单次 5 页上限;策划侧是同步加一屏,天然无并发,但要保留"一次操作最多 5 步"与"到顶即停"的边界。 3. **补上滚动锚定补偿**:取页前后记 `scrollHeight`,合并后 `scrollTop += 新 scrollHeight − 旧 scrollHeight`,保持用户当前可视内容不动。这同时掐掉"贴顶 → 自动取页 → 视野被推向更早内容 → scroll 事件递归触发 → 一路拉到整份历史"的连锁。补偿只在"取页前就贴顶或未填满"时做;用户主动滚回底部后不再自动取页(Direct 侧沿用 `shouldFollowLatestRef` 语义)。 4. **同步既有约定文档**(本次是**有意变更**既有口径,不是补漏实现): - `docs/technical/【技术方案】DirectProject Codex原始历史与异常恢复-2026-09-04.md:95`("必须显示『显示更早的对话』入口,并允许按钮或滚动触发"); - `docs/project-memory/plans/【里程碑】DirectProject Thread Manager事件订阅-2026-09-15.md:47`; - `docs/project-memory/shared-memory/decision-log.md:596-601`(新增一条决策:入口由按钮改为自动加载 + 允许锚定补偿); - `chat/history/directHistoryPaging.ts:8` 注释里的「显示更早」措辞。 5. **测试**: - `apps/ai-game-creator-shell/tests/directProjectProcessStatus.test.tsx:28-32,62-66` 去掉 `onLoadEarlierHistory`; - `planning` 侧渲染用例去 `onShowEarlierMessages`; - 新增回归网两例:① 首屏不满一屏 + `hasMore=true` → 无任何点击自动出现更早回合;② 贴顶取页后可视首条不变(锚定补偿)。变异验证:把"未填满"判据与补偿分别去掉,两条用例各自变红。 ## 范围 - 会话区入口表现与自动加载时机:`DirectProjectConversation` / `DirectProjectChatView` / `App.tsx` 的策划链路 / `styles.css` / `directHistoryPaging` 注释与既有约定文档。 - **不动**后端切片契约(`read_direct_project_history_slice` 的 `limit` / `beforeItemId` / `hasMore` 语义)、`historyLoadingRef` 并发闸、5 页上限、失败保留已成功页的既有行为。 ## 验收判据 - 会话区不再出现「显示更早的对话」按钮(两个面板都不出现);`rg message-history-more` 只剩 `.message-action` 那条样式。 - 首屏不满一屏且还有更早历史 → 无需任何操作,自动续拉直到可滚动或历史取尽。 - 用户滚到顶部 → 自动取更早的回合,且可视内容不跳动(取页前后可视首条同一条消息)。 - 一次操作最多 5 次请求的上限、`hasMore=false` 早停、单页失败保留已成功页、用户滚回底部后停止自动取页,行为全部不变。 - `npm run ai-game-creator-shell:typecheck`、AGC 前端定向用例、`npm run check:encoding`、`git diff --check` 通过。 ## 附 - 触发场景截图见评论。
suzmii added the
Priority
Medium
3
Kind/Enhancement
labels 2026-09-24 15:16:26 +08:00
Author
Member

触发场景截图(505×331,AGC 工作台 · DirectProject 项目对话):

会话区顶部整条「显示更早的对话」按钮占掉了列表第一行;这张图里它下方只有一条回合,列表根本没装满一屏 —— 此时 scrollTop 恒为 0、不会产生 scroll 事件,挂在 onScroll 上的自动取页整条失效,按钮成了唯一入口。

按钮还是全宽次级按钮,视觉权重和真实回合内容抢第一眼。
agc-show-earlier-button.png

触发场景截图(505×331,AGC 工作台 · DirectProject 项目对话): 会话区顶部整条「显示更早的对话」按钮占掉了列表第一行;这张图里它下方只有一条回合,列表根本没装满一屏 —— 此时 `scrollTop` 恒为 0、不会产生 scroll 事件,挂在 `onScroll` 上的自动取页整条失效,按钮成了唯一入口。 按钮还是全宽次级按钮,视觉权重和真实回合内容抢第一眼。 ![agc-show-earlier-button.png](/attachments/b5edda11-1fc2-4fea-8084-78463984a8fe)
k88936 self-assigned this 2026-10-02 16:35:21 +08:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GenarrativeAI/Genarrative#510