前言¶
DSH 的 Web 侧栏里,会话行自带置顶:hover 出现按钮,点一下钉到最前,置顶后不再 hover 时行尾留一枚灰色实心图钉。工作区(文件夹)行没有这个入口,只能靠拖拽排序;而且新建工作区会被宿主前插到列表最前,已经手工排好的次序很容易被打乱。
本文介绍的插件 dsh-workspace-pin 就是把「会话置顶」那套图钉原样补到工作区行上,视觉与交互直接复用官方实现,不改 dsh 自身任何文件。插件由 Richard 维护,分类为客户端插件,仓库版本 0.3.0,许可证 MIT。
这是什么¶
一句话定位:给 DSH Web 侧栏的工作区(文件夹)行补一个与会话置顶同款的图钉按钮,点击即把该工作区钉到列表最前,置顶集合由宿主持久化,跨浏览器和清缓存都不丢。
它解决的问题有两个:一是工作区行没有置顶入口,二是工作区顺序仅靠拖拽维护,容易被新建工作区抢占顶部位置。
核心功能¶
下面介绍的能力均可在 README 中核对。
- hover 任一工作区行时,行尾出现图钉按钮,位置在官方「…」和「+」旁边,最右;点击钉到列表最前,再点一次取消置顶。取消不会把工作区挪回原位。
- 置顶按钮复用官方按钮类名(
Rows.module.css的*_iconButton)、同一套 16×16 尺寸、--dsw-radius-xs圆角、label-tertiary静止色 / hoverlabel-primary、无 hover 背景,图标用官方 14pxIconPinOutline/IconPinFill。 - 悬浮提示用官方
Tooltip,参数side: bottom、align: end、delayMs: 500、portal: true。 - 置顶后无 hover 时,行尾出现与官方
*_pinIndicator同度量、同配色的灰色实心图钉,行一 hover 就让位给悬浮按钮。 - 置顶集合存在宿主半边,跨浏览器、无痕窗口、清站点数据、换设备都不丢。
- 页面加载、工作区列表变化、页面重新可见时,已置顶工作区会被重新排到最前,新建工作区被宿主前插时置顶项仍回到顶部。
- 不改 dsh 源码,不 fork dsh,卸载即恢复原生侧栏。
唯一的实现差异:官方静止标记用 margin-left: 6px(会话行 gap: 0),插件把 margin-left 取 0,由工作区行自身的 gap: 6px 承担同样间距。
安装¶
插件没有提供 dsh plugin add 形式的命令,安装由仓库自带的脚本完成。安装脚本只动三处:把插件包复制到 profile 的 plugins 目录、在 node_modules 里建 junction / 软链、把 cordis.patch.yml 里的 insert 块追加进 profile 的 cordis.patch.yml;前两处会先备份到 ~/.dsh-backup-<时间戳>/。
Windows(PowerShell):
git clone https://github.com/Richard2091/dsh-workspace-pin.git
cd dsh-workspace-pin
pwsh -File .\install.ps1
只有 Windows PowerShell 5.1 时可改用:
powershell -ExecutionPolicy Bypass -File .\install.ps1
macOS / Linux:
git clone https://github.com/Richard2091/dsh-workspace-pin.git
cd dsh-workspace-pin
sh install.sh
安装后刷新浏览器里的 DSH Web 页面即生效,profile 配置与插件文件由宿主 HMR 重组;如果宿主没有热加载新文件,重启一次 dsh web 即可。
验证与使用¶
安装后在控制台执行下面两条检查:
window.__dshWorkspacePinVersion
window.__dshWorkspacePinStorageMode
前者期望 "0.3.0",后者为 "host" 表示已连上宿主状态;若为 "cache",说明只加载了浏览器半边或宿主未热加载,此时退回 localStorage 缓存模式,不跨浏览器。
日常使用:
1、hover 任一工作区行,行尾出现图钉按钮;
2、点一下置顶,该工作区钉到列表最前;再点一下取消;
3、所有连到同一台 DSH 的浏览器和设备看到的是同一份置顶集合。
数据位置与重置¶
工作区置顶集合 <DSH_HOME>/storages/dsh-workspace-pin/state.json
工作区显示顺序 宿主 workspace registry(workspace.json 的 global.workspaceIds)
浏览器 localStorage 仅作本地缓存/旧数据迁移源,键 dsh.workspace-pin.v1
默认路径下置顶集合位于 ~/.dsh/storages/dsh-workspace-pin/state.json。重置置顶:删掉 state.json 后刷新页面,或向状态路由发送 {"op":"set","pinned":[]}。
也可以用条目 config 的 stateFile 把状态文件指到别的位置:
- insert:
- id: workspace-pin
name: 'dsh-workspace-pin'
config:
stateFile: 'D:\dsh-data\workspace-pin.json'
实现原理¶
宿主半边(lib/index.js)用官方 ctx.webServer.register() 注册一条精确路由 GET|POST /plugins/dsh-workspace-pin/state,请求准入复用官方 ctx.connection.requestRejection()(Host/Origin 围栏加浏览器会话鉴权),未认证请求返回 401、跨源写请求返回 403。状态文件写入走「临时文件 + rename」原子替换;pin / unpin 是增量操作,由宿主串行化读改写,多浏览器并发置顶不会互相覆盖;set 仅用于旧数据迁移。宿主半边不新增任何依赖,只用 Node 内置模块。
浏览器半边(lib/client.js)首帧先用 localStorage 缓存把图钉画出来,随后 GET 宿主状态对齐,宿主才是数据源。点击时本地立即生效(乐观更新),再 POST {op:"pin"|"unpin"},用宿主返回的权威集合校正 UI;失败只告警并退回本地缓存模式,不影响已生效的操作。页面重新可见时再向宿主对齐一次。按钮通过平台模块表用官方 React、Tooltip、IconPinFill、IconPinOutline 渲染;官方 UI 原语不可用时退回等价兜底样式与原生 title。旧版本升级时,若宿主为空而本机 localStorage 有旧置顶集合,会一次性 set 迁移到宿主。
兼容性与已知限制¶
在 DSH 0.2.1-rc.2(Web GUI)上实测,依赖官方工作区行 DOM、ctx.workspaces.insertBefore 客户端服务、ctx.webServer / ctx.connection 宿主服务,以及平台模块表里的 react / react-dom/client / @deepseek-ai/dsh-client-ui-primitives。dsh 大版本升级后如果官方行结构、类名、模块表或宿主服务变化,插件需要跟着适配。
需要留意的几点:
- 插件依赖官方工作区行的 DOM 结构(
[data-row-key^="workspace:"]、行尾 actions 容器)和Rows.module.css的类名度量,官方调整时插件需要同步更新。 - 页面加载时把已置顶工作区排到最前,这是一次真实的顺序写入,不是纯视觉排序。
- 宿主状态文件与宿主 workspace registry 是两份独立数据,不要在
dsh web运行时手改,会被内存状态覆盖;备份迁移时整目录拷贝即可。 - 以后在 profile 里跑
pnpm install会清掉安装脚本建的软链,重跑一次安装脚本即可,脚本是幂等的。 - 注销后
storages/dsh-workspace-pin/state.json不会被自动删除,需要的话手动删掉。
适用场景与注意¶
适合用 DSH Web 侧栏管理多个工作区、希望常用工作区稳定排在顶部的人。插件以当前 dsh web 进程的权限运行,会读写 profile 的 plugins、node_modules、cordis.patch.yml 以及宿主 storage 目录,安装前建议先阅读仓库源码与 MIT 许可证,确认与现有 profile 不冲突。
卸载¶
pwsh -File .\uninstall.ps1 # Windows
sh uninstall.sh # macOS / Linux
或手动删掉三处:cordis.patch.yml 里的安装块、node_modules 里的软链、plugins 里的插件目录,然后刷新页面。已写入宿主的工作区顺序会保留;置顶集合文件需要手动删除。
小结¶
dsh-workspace-pin 做了一件很窄的事:把官方会话置顶的图钉交互原封不动搬到工作区行上,并把置顶数据交给宿主持久化。它不改 dsh 源码,有自己的卸载脚本和三个点的说明文档,代价是依赖官方行结构的当前形态。对多工作区用户来说,这比反复拖拽排序省事。
目录页:https://www.skillhub.cn/plugins/Richard2091/dsh-workspace-pin
GitHub:https://github.com/Richard2091/dsh-workspace-pin