DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

wjingshan /

wjingshan/dsh-sidebar-focus

Verified

Order and disclosure for the DSH left sidebar driven by what is actually running: busy workspaces and active sessions float to the top, an idle workspace stays folded. Five switches, each reversible.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@a9c4ebca

dsh-sidebar-focus

左侧工作区的排序与展开,按「有没有在跑」来决定。五条规则,每条一个开关,位置在 插件页 → 点开 dsh-sidebar-focus 之后的详情页里(在描述与行列表之间)。

安装

dsh plugin --profile web add dsh-sidebar-focus

还没上 npm 时用 GitHub 源:

dsh plugin --profile web add github:wjingshan/dsh-sidebar-focus

装完刷新页面即可 —— 本插件是纯客户端(宿主半身是空的),不需要重启 dsh web。

它做什么

开关 默认 作用
置顶正在运行的工作区 开 有会话在跑、或正在等你的工作区排到列表最前。只影响显示,你手动拖出来的工作区顺序从不被改写
自动展开正在运行的工作区 开 有会话在跑、或正在等你的工作区自动展开。宿主本身只在「当前会话所在的工作区」上这么做,这条把它扩展到所有在跑的工作区
置顶正在进行的会话 开 运行中与等待你处理的会话排到所属工作区的最前
收起没有运行的工作区 开 没有会话在跑的工作区保持折叠
保留未读完成提醒 开 含「已完成未查看」的工作区不自动折叠,避免刚跑完的会话被收起来

交互语义:什么时候它不接管

自动折叠最烦人的失败模式是「你点开、它立刻折回去」。所以两侧都留了 意图豁免:

  • 你亲手展开一个空闲工作区 → 它保持展开,插件不再碰它,直到这个工作区重新变忙再变闲;
  • 你亲手折叠一个正在运行的工作区 → 它保持折叠,插件不替你展开,同样直到忙碌状态再次变化。

豁免只在本次页面会话内有效,刷新后回到规则本身。判断依据是 aria-expanded 上不是本插件 写出的翻转——所以「搜索结果跳转」「新建会话」这类宿主自己的展开,也被当成你的意图而保留。

另外两条不参与自动折叠的例外:

  • 未分组(Ungrouped)永不折叠:那是散落会话的收容所,不是谁主动选的工作区;
  • 当前选中会话所在的工作区保持展开:否则切换会话会落到一个被折起来的组上 (宿主的自动展开只对「没有存过状态」的组生效,而本插件会写状态)。

做法,以及为什么

  • 排序不移动 DOM:列表列原本是 overflow-y:auto 的块容器,order 对它无效;插件先把它变成 flex 列([data-wsf-rank-tree]),再用 order 给忙碌工作区 / 活动会话排名。DOM 节点从不移动, 所以 React 的 reconciliation 与内置的 FLIP 行动画都不受影响。
    • 排序是纯展示:不写 Workspace.sessionIds,也不碰你手动排序的结果。
  • 折叠是一次状态写入:折叠的组根本不渲染会话行(宿主的 deriveGroups 对折叠组返回空 sessions),所以 DOM 层做不到,必须改展开状态本身。写入走宿主自己的视图 store: ctx.get('uiWorkspace').view.setGroupExpanded(key, expanded),键就是工作区 id。
  • 「有没有在跑」不能只读行:只看 DOM 的判据在这里必然出错——组一折起来就没有行可读,于是 「里面有会话开始跑了」永远看不见,那个工作区会一直关着(用户报过:正在运行的工作区被折叠,打不开)。 忙碌判定因此改为读 Session 状态快照 useSessionStatus(running / pendingInteraction / completionUnread,与三条判据一一对应)加 Workspace 成员表 useWorkspaces (items[].sessionIds 说明哪些会话属于哪个工作区)。这两个事实与「有没有渲染成一行」无关, 折叠态照样成立,所以折叠中的工作区一旦开工就会被看见并展开。 两个 hook 由挂在 shell.overlay 上的零渲染桥接组件发布给 watcher(选它只因为那个席位永远挂载)。 行仍然照读——行级标记要用,快照未就绪时也要回退;两个来源取并集,任一见到在跑就不许关。
  • 所有开关都是开关:关闭时对应的 data-wsf-* 标记会被移除,CSS 规则随之失效,侧栏回到原生 布局与原生折叠行为——不做「半开」状态。

依赖的宿主契约(实测于本 profile 的内置 dsh-client-ui-workspace)

事实 来源
会话列表是 div[role="tree"] AnimatedRows.render
工作区行是 div[data-row-key="workspace:<key>"][role="treeitem"][aria-expanded],其父元素即组的 section renderGroup / ProjectRowItem
会话行是 div[data-row-key="session:<id>"][role="treeitem"][aria-selected],第一个子元素是该行自己的状态槽 SessionNodeItem
状态点带 data-state ∈ {ongoing, warning, done, error, idle} ui-primitives 的 StateDot
展开状态存在 dsh.workspace.view.v5,groupExpansion[key] 显式为 false 才折叠 createWorkspaceViewStore / deriveGroups
接口是 ctx.get('uiWorkspace').view.setGroupExpanded(key, expanded) UiWorkspaceService 的 view 字段
折叠的组不渲染任何会话行,所以运行状态必须另有来源 deriveGroups 的 GroupNode.sessions
槽位标准钩子 useSessionStatus / useWorkspaces 提供状态快照与工作区成员 shell.overlay 的 standardProps
WorkspaceSnapshot.items[].sessionIds 是「谁属于哪个工作区」 dsh-api-workspace-controller 的 WorkspaceView / WorkspaceSnapshot

这些是构建产物的结构,不是文档化 API:宿主升级后如果结构变了,插件会安静地什么都不做 (data-wsf-* 标记无处可落),而不是弄坏侧栏。若 uiWorkspace.view.setGroupExpanded 不存在, 折叠会被整体关闭,并在该插件的详情页上显示告警、控制台打印原因——不会静默失败。

已知限制

  • 不折叠未分组,理由见上;如果你要连它一起收,改 scanGroup 里的 key === '' 判断。
  • 自动折叠写的是宿主自己的视图偏好:被自动折起来的工作区,其 groupExpansion[key] 会以 false 持久化。卸载本插件后它们会保持折叠——手动点开即可恢复,或在插件页里禁用这个包再刷新。
  • 子工作区(树形分组)不参与置顶:子组在父组的 role="group" 容器里,不是列表列的直接子元素, order 在那里无效。会话级排序不受影响。
  • 状态判定只读「运行中 ongoing」与「等待你 warning」;error 不参与。

验证状态

已验证:

  • node --check 通过;manifest 解析通过;
  • 安装返回 application: applied,profile 的 dependencies 与 dsh.profile.bundles 都已登记;
  • 实时客户端注册已生效:plugins.bundle.config 席位上出现了 dsh-sidebar-focus 这个 key (cordis_inspect_query 可见)。插件页只在存在该 key 的注册时才渲染那块配置 (owner 的判据是 ledger.bundles.has(pkg.name)),所以这一条同时证明详情页里会出现这 5 个开关;
  • 原先在「设置 → 通用」的 5 行已确认从 settings.general.item 移除,不会两处重复;
  • 状态桥接已确认挂载:shell.overlay 的实时占用者里有 dsh-sidebar-focus.status-bridge, 而该席位的 standardProps 同时提供 useSessionStatus 与 useWorkspaces。

未验证(本机 GUI 需要启动令牌,agent 浏览器无法进入;按插件规范的验证边界,未用截图或模拟 DOM 冒充):

  • 视觉结果(置顶后的实际顺序、flex 化后的行高与间距、浅色/深色两套主题下的观感);
  • 五条规则在真实运行/空闲会话上的实际效果,尤其是这一条:在一个已折叠的工作区里启动会话, 它应当自动展开。我能证明的只到「判据已换成不依赖行渲染的快照」;真实会话的启动我驱动不了;
  • 与内置 FLIP 行动画、拖拽排序的共存表现。

自查方式:刷新 Web 页面 → 打开一个正在跑的工作区(应自动展开并置顶)→ 打开一个空闲工作区 (应保持折叠,你手动展开后应保持展开)→ 控制台不应出现 [dsh-sidebar-focus] 开头的报错。

—/ 5

No ratings yet

Verified DSH bundle

Commit a9c4ebca4907

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout