Skip to content

fix(sidebar): 展开态 touched 位、顶栏严格置顶 + draft 进左栏、模型弹层越界导致的整页横滚 - #68

Merged
Jaxton07 merged 7 commits into
mainfrom
fix/sidebar-touched-pinned
Sep 20, 2026
Merged

Jaxton07 merged 7 commits into
mainfrom
fix/sidebar-touched-pinned

Conversation

@Jaxton07

Copy link
Copy Markdown
Owner

问题(四个相关但独立的小毛病)

  1. 展开态的状态歧义:expandedGroups: [] 身兼两义——「还没初始化过」与「用户主动全折叠」。结果是当前项目最后一个展开组折不掉(切会话又被默认集复活)。
  2. 顶栏把 draft 当例外:顶栏本该严格只显示置顶会话,但 draft 被拼进顶栏(点「+」后多一个胶囊),与「顶栏 = 置顶」的产品口径不一致。
  3. 左栏看不到内存会话:左栏只列磁盘历史,刚建的会话在发首条消息前不可见;draft 需要一个正经的入口(标题「新会话」、右键只能丢弃)。
  4. 模型弹层越界拖走整页:ModelPicker 弹层 left-0 在窄窗越过视口右缘 → Chromium 对 #root 程序性横滚(实测 scrollLeft 0→35.5),整页左移、顶栏最左按钮被裁掉。

改动

  • 展开态显式 touched 位:UiState.expandedGroupsTouched(shared 类型 + main/ui-state.ts normalize:显式布尔优先,缺字段按记录是否非空推断,脏值清洗);renderer 侧 setExpandedGroups 同一次 set 写两个字段 + 单补丁落盘;派生判据从「数组空不空」改为 touched,toggleExpandedGroup 增 touched 参(否则「全折叠后点开一个组」会隐式复活默认集)。
  • 顶栏严格置顶:selectBarSessions 删掉 draft 拼接与例外注释;删顶栏里不可达的 draft 分支(叉叉恒为取消置顶)与已无引用的 tabbar.discardDraft 键。
  • draft 进左栏:新增纯函数 mergeSidebarSessions(历史 + 内存,Map 保序去重、内存覆盖),合并结果同时驱动项目分组与会话分组;draft 行标题固定「新会话」/New session;右键菜单按 sidebarMenuKind 分支,draft 只有「丢弃新会话」(danger,纯本地 closeSession;只读子会话仍无菜单)。
  • 弹层改 right-0:ModelPicker 弹层向左展开,不再越界(含注释记录越界/横滚量值)。
  • i18n zh/en 同步(+sidebar.newSession、+sessionMenu.discardDraft)。
  • 文档:docs/INDEX.md(顶栏严格置顶 / 左栏合并视图 / touched 语义 / ModelPicker 定位职责,修正过期字段名 topBarVisible)、docs/PITFALLS.md(症状索引 +4 行;新增「空数组不能同时当未初始化与有效空值」「absolute 弹层越界 + autoFocus = 整页横向偷跑(含量测三纪律)」「renderer 单测跑 node 环境」)。

验证

npm run typecheck   ✅(shared / backend / desktop node+web)
npm run lint        ✅ exit=0(Checked 432 files)
npm run test        ✅ backend 55 files / 505 passed;desktop 43 files / 463 passed(合计 968 passed, 0 failed)
git show --check    ✅ 各 commit 无空白错误
  • CDP 确定性量值(脚本在 .local/debug/,已 gitignore)
    • 模型弹层四档(1100/900/700px 真实会话 + 1100px 居中 composer):修复前弹层右越界 +11.8~+12.0px、#root.scrollLeft 0→8~35.5、顶栏最左按钮 left 80→72/44.5;修复后全部归零(弹层完整在视口内、滚动量 0、左栏 width 恒 240、顶栏按钮 left 恒 80、搜索框仍 activeElement、ArrowDown/Enter 键盘导航与提交换模型正常)。
    • 顶栏/左栏 draft 24 条断言:建 draft 顶栏胶囊不变、左栏两行标题「新会话」、右键菜单恰一项「丢弃新会话」、丢弃后行与 store 同步、真实会话菜单未回归、发首条消息转正后左栏行数不变。
    • 折叠状态跨重启:折掉所有分组 → 盘上 {expandedGroups: [], expandedGroupsTouched: true} → 重启 dev → 仍全折叠(此时无活跃会话也没有默认展开源)。
  • 定向单测:sidebar-groups + ui-preferences + main/ui-state 三文件 49 passed。
  • 菜单项 builder 没有单测(renderer 单测跑 node 环境、无 DOM/JSX 基建),改由纯函数单测 + CDP 手测覆盖菜单形态。

行为不变(回归面)

draft 不写盘、重启即消失;普通会话删除确认流程不变;未新增 IPC、未改 backend/SDK 生命周期(改动清单里无 backend/IPC 文件);draft 丢弃沿用既有 closeSession 的纯本地分支。

Checklist

  • npm run typecheck passes
  • npm run test passes
  • New user-facing strings were added to both zh and en dictionaries
  • No API keys or sensitive data included

- shared UiState.expandedGroupsTouched(缺字段按记录非空推断,兼容旧文件)
- main ui-state normalize:显式布尔优先,脏值/缺失才推断
- ui-preferences:init 读取;setExpandedGroups 一次 set + 单个补丁原子写两字段
- lib/sidebar-groups:derive 判据从「数组空不空」改为 touched;toggleExpandedGroup 以 touched 决定起点
- useExpandedGroups/Sidebar 接线(全部折叠后再点一个组只展开它,不回退默认集)
- selectBarSessions 去掉 draft 例外:顶栏严格 = 置顶表(SessionTabBar 删掉不可达的 draft 分支)
- 新增纯函数 mergeSidebarSessions(历史 + 内存,按 id 去重、内存覆盖),Sidebar 用它同时驱动项目表与会话分组
- SessionRow:draft 行标题固定「新会话」
- session-menu:sidebarMenuKind 判定 + draftSessionMenuItems(仅「丢弃新会话」一项,走纯本地 closeSession)
- i18n 双字典:+sidebar.newSession / +sessionMenu.discardDraft,删顶栏已无用的 tabbar.discardDraft
left-0 让 288px 弹层从按钮左缘向右展开:1100px 窗口就右越界 11.8px(900/700px 下 12px+),
搜索框 autoFocus 触发 Chromium 对 #root 的程序性横向滚动(overflow:hidden 拦不住)——
实测 #root.scrollLeft 0→8/35.5、顶栏最左按钮 left 80→72/44.5,即左栏与顶栏被挤压。
改为 right-0(弹层右缘贴按钮右缘):弹层 left/right = 659/947(< innerWidth),
#root.scrollLeft 恒 0,左栏宽度与顶栏按钮位置零偏移;bottom-full/w-72/autoFocus/键盘导航不变。
…,PITFALLS 补三条新坑

- INDEX:sidebar-groups(mergeSidebarSessions + touched 起点)、selectBarSessions 顶栏范围、
  ui-preferences expandedGroupsTouched、session/ 与 sidebar/ 两行同步、模型弹层定位职责、
  修正过期字段名 topBarVisible → barSessionsVisible
- PITFALLS:空数组不能同时当「未初始化」与「有效空值」;absolute 弹层越界 + autoFocus
  触发 #root 程序性横滚(overflow:hidden 拦不住,含量测三纪律:selector 限定作用域 /
  扫多档窗口宽 / 侧栏行用行高而非标题分辨);renderer 单测跑 node 环境测不了 i18n 与 JSX
- ModelPicker 注释量值表述修正(右越界约 12px;35.5px 是窄窗口的根横滚量)
…itest classic)

- docs/INDEX.md:182:**…** 单层粗体(原来在粗体内嵌了 **严格置顶表**,Markdown 不支持重叠)
- docs/PITFALLS.md:明确「应用构建/tsconfig 预期 automatic → 源码无 import React;Vitest 路径编成 classic → React is not defined」,删掉自相矛盾表述
- 纯文档,无业务代码改动
@Jaxton07
Jaxton07 merged commit d38c4e6 into main Sep 20, 2026
1 check passed
@Jaxton07
Jaxton07 deleted the fix/sidebar-touched-pinned branch September 20, 2026 10:40
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