fix(web): close details when current session changes

This commit is contained in:
NI0317
2026-07-29 11:21:13 +08:00
parent 1f242753ec
commit 406cd3602b
9 files changed
+210 -26

No files matched your search

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-07-29-web-details-session-lifecycle.md
2026-07-29-web-details-session-lifecycle.md: 3483720ef642e87bf2f3ffa0d4cf9677711a3354
2026-07-29-web-details-session-lifecycle.zh.md: 7570f4ad045be7607beb98295551bb50403620c3
@@ -0,0 +1,29 @@
# Agent Note: Web details follow the current Session lifecycle
Status: implemented
English | [中文](2026-07-29-web-details-session-lifecycle.zh.md)
## Problem
The details entry is Session-scoped, but its grid width is root-scoped and persisted. Changing the current Session replaced or removed the details content without closing that root column, so New Session could show its composer beside an empty details panel that still consumed 360 pixels. The same ownership gap applied to ordinary Session switches and to selection invalidation after a Session disappeared.
## Decision
`AppFrame` derives one details owner from the authoritative Session projection after the Session baseline is ready: the current Session must still exist and must not be blank. The first ready active Session is baseline restoration, so an open details width may survive a browser refresh. A first ready New Session state has no details owner and closes stale persisted state.
After baseline restoration, every details-owner change closes the panel through the layout store before paint. This covers active-to-active navigation, active-to-blank New Session, clearing the current selection, and invalidation after deletion. Returning to the earlier Session keeps details closed because the root store records the close; the per-Session chat selection remains owned by the session-scoped store described by the [slot system standard](../architecture/2026-07-22-slot-type-chain-implementation.md).
Manual close and reopen inside one unchanged active Session retain their existing behavior. The lifecycle effect changes neither sidebar actions nor the [Workspace-owned New Session flow](../feature/2026-07-25-workspace-ui-product-flow.md), composer drafts, Session navigation, or concession-chain resizing.
## Alternatives considered
**Close details in the New Session click handler.** Rejected because top-level New Session, Workspace row actions, the Workspace picker, ordinary Session rows, and removal can all change the owner. An entry-point patch would leave the shared lifecycle inconsistent.
**Persist panel geometry per Session.** Rejected because the product contract needs stale context removed, not a new map of remembered widths. Per-Session geometry would also reopen details when users return, contrary to the chosen close-on-leave behavior.
**Only hide the details component when no Session is current.** Rejected because a blank Session is still current, and removing content without zeroing the grid track is the reported defect.
## Consequences
Leaving an active Session forgets any dragged details width, since the existing close action writes zero and reopening uses the contract default. Refreshing an active Session preserves its open panel, while refreshing New Session clears stale persisted geometry. The layout behavior test covers active, blank, missing, switch-back, and baseline-restore states; the keyless browser e2e drives the shipped composition from an active Session through New Session and back while checking the full grid track and browser errors.
@@ -0,0 +1,29 @@
# Agent Note: Web 详情栏遵循当前会话生命周期
Status: implemented
[English](2026-07-29-web-details-session-lifecycle.md) | 中文
## 问题
详情入口由会话作用域拥有,而其网格宽度由根作用域拥有并持久化。切换当前会话时,系统会替换或移除详情内容,却不会关闭根布局中的该列。因此,New Session 可能在空白详情面板旁显示 composer,而该面板仍占用 360 像素。普通会话切换,以及会话消失后选中状态失效,同样存在这一所有权缺口。
## 决策
会话基线就绪后,`AppFrame` 会从权威会话投影派生唯一的详情 owner:当前会话必须仍然存在,且不得为 blank。首次就绪的活动会话属于基线恢复,因此浏览器刷新后可以保留已打开的详情宽度。若首次就绪时处于 New Session,则不存在详情 owner,系统会关闭陈旧的持久化状态。
基线恢复后,详情 owner 每次变化都会先通过布局 store 关闭面板,再进行绘制。这涵盖活动会话之间的导航、从活动会话进入 blank New Session、清除当前选中项,以及删除后选中状态失效。返回先前的会话后,详情仍保持关闭,因为根 store 已记录这次关闭;逐会话的聊天选中项继续由 [slot 体系标准](../architecture/2026-07-22-slot-type-chain-implementation.md)所述的会话作用域 store 拥有。
在同一个未变化的活动会话内手动关闭和重新打开详情栏,仍保持原有行为。该生命周期 effect 既不改变侧边栏操作,也不改变 [Workspace 拥有的 New Session 动线](../feature/2026-07-25-workspace-ui-product-flow.md)、composer 草稿、会话导航或让步链缩放。
## 考虑过的替代方案
**在 New Session 点击处理器中关闭详情栏。** 之所以否决:顶层 New Session、Workspace 行操作、Workspace picker、普通会话行和移除操作均可改变 owner。入口级补丁会使共享生命周期继续保持不一致。
**按会话持久化面板几何信息。** 之所以否决:产品契约需要移除陈旧上下文,而不是新增一张保存各宽度的映射。按会话保存几何信息还会在用户返回时重新打开详情栏,与选定的离开即关闭行为相悖。
**仅在当前没有会话时隐藏详情组件。** 之所以否决:blank 会话仍是当前会话;只移除内容而不将网格轨道归零,正是本次报告的缺陷。
## 后果
离开活动会话会忘记拖动后的详情宽度,因为现有关闭操作会写入零值,重新打开时则使用契约默认值。刷新活动会话会保留已打开的面板,而刷新 New Session 会清除陈旧的持久化几何信息。布局行为测试覆盖 active、blank、missing、切回和基线恢复状态;无密钥浏览器 e2e 则驱动已交付的组合从活动会话进入 New Session 再返回,同时检查完整网格轨道和浏览器错误。