dsh-sidebar-color
给 DSH 侧边栏的工作区文件夹按身份上色:同一个文件夹永远是同一个颜色,重排、拖拽、重启都不变。
配色由 OKLCH 感知均匀色彩空间动态生成,深浅主题同色相、自动避开背景色相。
同时把当前对话的标题和它正在转的圆环显示为红色,文件夹全部展开、对话列表很长时也能一眼找到自己在看哪一个。
自带可视化设置面板(右下角),调色不用改代码。
版本 0.5.0 · 目标 DSH 0.2.1-rc.2 · MIT · 纯展示层,不改动任何数据
改名说明:本插件原名
dsh-workspace-color,0.5.0 起更名为dsh-sidebar-color。 旧版本用户升级时,面板里的设置会自动迁移,不会丢失。
目录
效果预览

在截图中可以对应到:
| 位置 | 对应功能 |
|---|---|
| 每个工作区的文件夹图标与名称 | ① 实色(每个工作区颜色不同) |
| 文件夹行整行淡彩底 | ② 同色 14% |
| 文件夹下展开的对话行底色 | ③ 同色 7% |
| 「当前对话标题标红功能」这一行 | ④ 标题显示为红色 |
| 该行左侧正在转的圆环 | ⑤ 红色(只染运行中的圆环) |
| 其它对话行 | 保持官方黑色,时间标签不受影响 |
| 右下角彩虹小圆点 | 设置面板入口 |
功能
一、工作区配色(第 1–3 项)
用 6 种柔和配色给每个工作区打上「同色系三层深浅」:
| 编号 | 位置 | 效果 |
|---|---|---|
| ① | 文件夹图标 + 名称 | 实色(最醒目) |
| ② | 文件夹行背景 | 同色 14% 淡彩 |
| ③ | 本工作区展开的对话行背景 | 同色 7% 淡彩 |
颜色由 workspaceId 做 sdbm 哈希取色,而不是按显示位置循环。因此搭配自动排序插件(如 dsh-workspace-recency)时,文件夹颜色不会跟着乱跳。
第 ③ 项用「直接子元素」选择器,只染本工作区自己的对话行,不会误染嵌套的子工作区。
二、当前对话红色标记(第 4–5 项)
| 编号 | 位置 | 效果 | 引入版本 |
|---|---|---|---|
| ④ | 当前对话的标题文字 | 红色(浅色 #D92B2B / 深色 #FF6B6B) |
0.3.0 |
| ⑤ | 对话运行中的转圈圆环 | 同款红色 | 0.4.0 |
两项都只改颜色,不动行底色、时间文字、状态标记、⋯ 菜单按钮。因为不动底色,同一工作区其它对话行的淡彩底和官方 hover 高亮都不受影响。
为什么只染「运行中」的圆环
行首那个位置官方一共会显示三种标记,颜色本身携带状态语义:
| 标记 | 含义 | 本插件是否改色 |
|---|---|---|
| 灰色转圈圆环 | 正在运行 | ✅ 改为红色 |
| 黄点 | 等待你操作(审批 / 计划确认 / 回答问题) | ❌ 保持官方黄色 |
| 绿点 | 已跑完但还没看过结果 | ❌ 保持官方绿色 |
| (无标记) | 空闲 / 已完成且已读 | — |
黄点和绿点本身就是提醒,刻意不动,避免削弱状态信息。
三、OKLCH 配色与防撞色(0.5.0)
OKLCH 色彩空间:配色不再写死 6 个十六进制值,而是用 OKLCH(感知均匀色彩空间)生成。
同样改变 L 值,人眼感受到的亮度变化是一致的——所以浅色主题和深色主题可以用同一色相、不同亮度生成一对,不会出现手工调色时「浅色发灰、深色发艳」的问题。
| 主题 | L(亮度) | C(饱和) |
|---|---|---|
| 浅色 | 0.55 | 0.11 |
| 深色 | 0.76 | 0.095 |
防撞色:运行时探测页面实际背景色相,把「冲突区」(背景色相 ±45°)整段让出来,在剩余安全弧里均分 6 个色相。
实测 6 个色相与背景色相的最小距离为 67.5°,远超阈值。
第一版写错过:曾用「整体顺延所有槽位」,但 6 个色相均匀分布在整圈上,任意转动必然有一个落在背景色相,永远无解(实测最小距离 0.0°)。正确做法是剔出冲突区后重排。
四、可视化设置面板(0.5.0)
屏幕右下角有一个 22px 的彩虹小圆点(默认 35% 透明度),点击打开设置面板:

| 设置项 | 作用 |
|---|---|
| 启用插件 | 总开关,关闭后所有效果失效 |
| 当前对话标题标红 | 开关 ④ |
| 运行中圆环标红 | 开关 ⑤ |
| 避开背景色相 | 开关防撞色 |
| 色1 ~ 色6 | 逐个微调色相(-60° ~ +60°),色块实时预览 |
| 浅色主题 亮度 / 饱和 | 调浅色下 6 色的整体明暗与浓淡 |
| 深色主题 亮度 / 饱和 | 同上,深色 |
| 恢复默认 | 一键还原全部设置 |
- 即时生效,无需重启
- 设置保存在
localStorage(键名dsh-sidebar-color:settings),跨重启保留 - 面板可拖动(按住标题栏)
- 点击面板外部任意位置即可关闭,也可点
✕
为什么不用官方设置页:实测
ctx.slots.register('settings.section', ...)在当前加载方式下不生效(设置页不会出现新条目),因此做成自建浮层。
安装
方式一:一键命令(推荐)
在终端执行:
# 桌面端
dsh plugin --profile desktop add github:lsb0554/dsh-sidebar-color
# dsh web(浏览器)
dsh plugin --profile web add github:lsb0554/dsh-sidebar-color
装完重启 DSH 即可。
方式二:一键脚本
下载本仓库后,在仓库根目录执行:
# Windows
powershell -ExecutionPolicy Bypass -File .\install.ps1
# macOS / Linux
bash install.sh
脚本会自动完成:复制插件 → 备份并登记 profile → 用 DSH 自带 pnpm 安装。
可选参数:
powershell -ExecutionPolicy Bypass -File .\install.ps1 -Profile web
bash install.sh web
方式三:手动安装
适合需要自行控制安装位置,或排查问题的情况。
前置条件
- DSH 0.2.1-rc.2(其他版本未验证,见兼容性)
- 能访问 DSH 配置目录
~/.dsh/- Windows:
C:\Users\<你的用户名>\.dsh\ - macOS / Linux:
~/.dsh/
- Windows:
先确定用哪个 profile
DSH 的插件装在 profile 目录里,目录名与客户端类型有关:
| 客户端 | profile 目录 |
|---|---|
| 桌面端(Electron 应用) | ~/.dsh/profiles/desktop/ |
dsh web(浏览器) |
~/.dsh/profiles/web/ |
看你机器上实际存在哪个即可:
# Windows
Get-ChildItem "$env:USERPROFILE\.dsh\profiles" -Directory
# macOS / Linux
ls ~/.dsh/profiles
下文用 ~/.dsh/profiles/<profile>/ 表示,请按实际目录名替换 <profile>。
安装步骤
把本插件目录放到
~/.dsh/plugins/下:~/.dsh/plugins/dsh-sidebar-color/编辑 profile 的
package.json(~/.dsh/profiles/<profile>/package.json),加入依赖。file:路径要用绝对路径(Windows 注意反斜杠转义,建议统一用正斜杠):"dependencies": { "dsh-sidebar-color": "file:C:/Users/<你的用户名>/.dsh/plugins/dsh-sidebar-color" }// macOS / Linux 示例 "dsh-sidebar-color": "file:/home/<你的用户名>/.dsh/plugins/dsh-sidebar-color"同一个文件里,把插件加入 bundles 列表:
"dsh": { "profile": { "bundles": [ // ... 其他插件 "dsh-sidebar-color" ] } }在 profile 目录下安装(用 DSH 自带的 pnpm v11):
cd "$env:USERPROFILE\.dsh\profiles\<profile>" pnpm installcd ~/.dsh/profiles/<profile> && pnpm install完全退出 DSH(包括系统托盘里的图标),再重新启动。
验证是否生效
装好后检查三处:
- 侧边栏的工作区文件夹图标 / 名称变成彩色 → 插件已加载
- 当前对话标题是红色 → 第 ④ 项生效
- 发一条消息,行首转圈圆环变红 → 第 ⑤ 项生效
- 右下角出现彩虹小圆点 → 设置面板可用
更新 / 升级
不要只替换 plugins 目录里的文件——那不会影响 DSH 实际加载的代码。见下一节。
标准流程:
# 1. 更新源目录(~/.dsh/plugins/dsh-sidebar-color/)
# 2. 同步到实际加载位置(关键且最容易忘)
Copy-Item -Recurse -Force "$env:USERPROFILE\.dsh\plugins\dsh-sidebar-color\*" `
"$env:USERPROFILE\.dsh\profiles\<profile>\node_modules\dsh-sidebar-color\"
# 3. 完全退出 DSH(含托盘)再启动
# macOS / Linux
cp -R ~/.dsh/plugins/dsh-sidebar-color/* ~/.dsh/profiles/<profile>/node_modules/dsh-sidebar-color/
或者重新跑一次 pnpm install(在 profile 目录下),它也会重新拷贝。
开发 / 修改这个插件(重要)
磁盘上存在两份副本
| 位置 | 作用 |
|---|---|
~/.dsh/plugins/dsh-sidebar-color/ |
源目录,pnpm install 从这里安装 |
~/.dsh/profiles/<profile>/node_modules/dsh-sidebar-color/ |
实际被 DSH 加载的那一份 |
pnpm install 会把插件 copy(复制) 进 profile 的 node_modules,不是软链接。
因此装好之后:改源目录 ≠ 改生效代码。DSH 加载的始终是 profile 里那份拷贝。
这条是实际踩过的坑:曾经只改了
plugins目录,重启后功能毫无变化,白白多排查了一轮。
修改流程
# 1. 改源目录
# $env:USERPROFILE\.dsh\plugins\dsh-sidebar-color\client.js
# 2. 同步到实际加载位置
Copy-Item "$env:USERPROFILE\.dsh\plugins\dsh-sidebar-color\client.js" `
"$env:USERPROFILE\.dsh\profiles\<profile>\node_modules\dsh-sidebar-color\client.js" -Force
# 3. 等几秒(热重载会自动生效),或手动重启 DSH
# macOS / Linux
cp ~/.dsh/plugins/dsh-sidebar-color/client.js \
~/.dsh/profiles/<profile>/node_modules/dsh-sidebar-color/client.js
热重载(实测修正)
DSH 内置 dsh-client-hmr 模块,客户端插件代码改动会被自动热重载,通常几秒内生效,不必重启。
实测案例:DSH 17:28 启动,17:34 改了
client.js,改完不重启、新功能直接可用。
但以下情况仍然需要完整重启进程:
| 情况 | 是否需要重启 |
|---|---|
改 client.js 里的代码 |
❌ 不需要,热重载自动生效 |
改 package.json(版本号、dsh 字段) |
✅ 需要 |
改 cordis.patch.yml(注册信息) |
✅ 需要 |
增删依赖 / 跑过 pnpm install |
✅ 需要 |
| 插件首次安装 | ✅ 需要 |
三条自检
改了没效果时,按顺序检查:
改的是不是真正加载的那份——profile 副本里有没有新代码:
Select-String -Path "$env:USERPROFILE\.dsh\profiles\<profile>\node_modules\dsh-sidebar-color\client.js" -Pattern '你新增的关键字'这是最常见的原因(改的是
plugins目录,而不是 profile 副本)。热重载有没有跑:等 5~10 秒再观察。若仍未生效,说明热重载可能没覆盖到这次改动,手动重启一次。
文件是否写坏:语法错误会让整段插件代码静默失效,表现为"插件好像没装"。用
node --check预检。
语法预检
改完 client.js 后可先做一次语法检查,避免写坏导致插件静默失效:
node --check "$env:USERPROFILE\.dsh\plugins\dsh-sidebar-color\client.js"
node --check ~/.dsh/plugins/dsh-sidebar-color/client.js
自定义颜色
推荐方式:用设置面板(右下角彩虹小圆点)。调色相、亮度、饱和度都可视化,实时预览,不用改代码。
下面是改代码的方式,适合批量或做发行版定制。
标题色 / 圆环色(④⑤)
:root{--ws-current-title:#D92B2B; --ws-running-ring:#D92B2B;} /* 浅色 */
body[data-ds-dark-theme]{--ws-current-title:#FF6B6B; --ws-running-ring:#FF6B6B;} /* 深色 */
工作区 6 色(①②③)
配色由 OKLCH 动态生成,不再写死十六进制。要改整体观感,调亮度档位:
const TONE = {
light: { L: 0.55, C: 0.11 }, // 浅色:中等亮度 + 中等饱和
dark: { L: 0.76, C: 0.095 }, // 深色:提亮 + 略降饱和
}
- L 调大 → 整体更浅(深色主题下更容易看清)
- C 调大 → 更鲜艳
- 具体每个槽位的色相,用设置面板的 6 个滑块调
想改色相分布算法,见 buildHues():
function buildHues(count, bgHue, conflictDeg) { ... }
// conflictDeg 默认 45:距背景色相小于 45° 视为撞色
想增删颜色数量:改 PALETTE 常量(默认 6),设置面板会自动跟着变成对应数量的滑块。
调整底色浓淡(②③)
/* 14% = 文件夹行底,7% = 对话区底,按需调百分比 */
--ws-row-tint: color-mix(in srgb, var(--ws-color) 14%, transparent);
--ws-sess-tint: color-mix(in srgb, var(--ws-color) 7%, transparent);
查看当前实际配色
在 DevTools(桌面端按 F12)Console 里执行:
window.__wsColorPalette
// 返回:{ lightBgHue, darkBgHue, hues, light, dark, minDistToLightBg, settings }
排错指南
文件夹没有颜色
| 可能原因 | 检查方法 |
|---|---|
| 插件未加载 | 看 profile 的 package.json 里 dsh.profile.bundles 是否含 dsh-sidebar-color |
| 依赖未安装 | profile 目录下 pnpm install 是否成功,node_modules/dsh-sidebar-color 是否存在 |
| 在设置面板里被关掉了 | 点右下角彩虹小圆点,检查「启用插件」是否被关闭(设置存在 localStorage,会跨重启保留) |
| 代码有语法错误 | node --check client.js 预检,语法错误会让插件静默失效 |
改了代码但没生效
见开发 / 修改这个插件。最常见原因是只改了 plugins 目录,而不是 profile 副本。改 client.js 一般由热重载自动生效,无需重启。
找不到设置面板
设置入口是屏幕右下角一个 22px 的彩虹小圆点,默认 35% 透明度(鼠标移上去才完全显现)。
- 如果没看到:确认插件已加载(侧边栏是否有颜色)
- 点击它打开面板,再次点击面板外部任意位置即可关闭
当前对话标题不是红色
| 可能原因 | 说明 |
|---|---|
| 打开的是「插件管理」/「任务管理」页面 | 官方会把「当前会话」置空,侧边栏不标红。这是正常行为,见已知取舍 |
| 该对话没有标题 | 新建的空会话显示「新对话」占位文本,同样会红 |
| 选择器失效 | 通常是 DSH 升级改了 DOM 结构,见兼容性 重新核对 |
转圈圆环不是红色
| 可能原因 | 说明 |
|---|---|
| 对话没在运行 | 只染 data-state="ongoing"。跑完就不转圈了,圆环消失属于官方行为 |
| 看到的是黄点 / 绿点 | 那两种状态按设计保持官方颜色 |
| 选择器失效 | 同上,DSH 升级后需重新核对 DOM |
两种红色都没出现
如果侧边栏连文件夹配色都没有,说明整个插件没加载,优先排查安装。 如果文件夹有颜色、但两个红色都没有,说明插件已加载但选择器没命中,多半是 DSH 版本变了。
建议用浏览器内核验证选择器(无需动真实环境):
// 在 DSH 的 DevTools(桌面端按 F12)Console 里执行,只读不写
document.querySelectorAll('[data-row-key^="session:"][aria-selected="true"] > span:nth-child(2)').length
document.querySelectorAll('[data-row-key^="session:"] > span:first-child svg[data-state="ongoing"]').length
- 返回
0:当前没有符合条件的行(正常,可能是没有选中会话 / 没有在运行) - 返回
≥1但颜色不对:选择器命中了但被更高优先级覆盖,需检查官方样式
卸载 / 回滚
- 从
dsh.profile.bundles移除"dsh-sidebar-color" - 删除
dependencies里的"dsh-sidebar-color"条目 - 在 profile 目录
pnpm install - 完全退出 DSH 再启动
由于是纯 CSS 注入 + 运行时打标签,卸载后不会留下任何残留:样式标签、打过 data-ws-* 属性的元素都会随插件卸载一起清理。
已知取舍
相邻文件夹可能同色
6 种颜色、多于 6 个工作区时,相邻文件夹偶尔会同色。这是「颜色绑定身份」与「相邻必不撞色」不可兼得的固有代价。
本插件优先选稳定——否则每次自动排序都会让所有颜色整体洗牌,比偶尔撞色更难受。
不在「主视图」时不标红
当前对话标红只作用于主视图里的那个对话。
点侧边栏底部的两个图标(插件管理 plugins / 任务管理 schedules)时,中间区域会从对话切换成对应的全局页面。这时官方会主动把「当前会话」置空(activePanelId !== null 时 current 被设为 undefined),侧边栏便没有任何一行标红。
这是跟随官方状态的正常表现,不是插件失效——此时对话区本身也已被那个页面替换掉了,标不标红没有意义。
圆环只在运行时可见
圆环是「正在运行」这个状态的视觉表现。跑完回到空闲后官方会整个移除该元素,所以圆环消失是正常的,不是被插件弄没了。
兼容性
针对 DSH 0.2.1-rc.2(Electron 44 / Chromium 152)验证。
所有依赖的 DOM 契约均对照 app.asar 源码核实,并用真实浏览器内核做了计算样式验证:
| 依赖 | 契约 | 稳定性 |
|---|---|---|
| 行标识 | data-row-key="workspace:<id>" / data-row-key="session:<id>"(未哈希) |
稳定 |
| 分组容器 | groupSection 内联 --dsh-workspace-indent,文件夹行是其第一个子元素 |
稳定 |
| 文件夹图标 / 名称 | 第 1 个 span / 第 3 个 span 内的 span | 结构位置 |
| 当前对话标记 | 行上 aria-selected="true"(SessionNodeItem,node.id === currentId) |
官方语义属性 |
| 对话标题 | 行内第 2 个直接子元素 | 结构位置 |
| 运行状态 | 行首第 1 个子元素里的 <svg data-state="ongoing"> |
官方数据属性 |
| 圆环绘制方式 | 内部 circle 靠 stroke 绘制(fill:none,改 color 无效) |
需实测 |
| 深色主题 | <body data-ds-dark-theme> 存在性属性 |
稳定 |
不依赖哈希类名
官方用的是 CSS Modules,类名带构建哈希,例如:
- 标题 →
hIlkoa_title - 圆环 →
_spinner_1i3xo_37
hIlkoa_ / _1i3xo_ 这类前缀每次重新打包都可能变化。本插件一律不按类名定位,只走 data-* 属性 + 子元素位置,所以 DSH 小版本升级通常不会失效。
DSH 大版本升级后
如果升级后功能失效,通常是因为 DOM 结构变了。核对方法:
- 按 F12 打开 DevTools(桌面端支持)
- 用排错指南里的
querySelectorAll逐条验证选择器 - 若返回 0,说明契约变了,需按新结构更新选择器
实现原理
本插件是纯展示层,不读写任何数据、不调用任何服务、不改 app.asar。
两个半侧
| 文件 | 作用 |
|---|---|
index.js(宿主侧) |
空实现。仅在 Loader 注册,供 profile 识别 |
client.js(浏览器侧) |
全部逻辑所在 |
浏览器侧做了什么
- 注入一段 CSS(
<style id="dsh-sidebar-color/style">)——包含全部 5 项功能的样式规则 - 用
MutationObserver监听 DOM 变化,给每个工作区文件夹行和它的分组容器打上data-ws-row="N"/data-ws-section="N"标签(N由workspaceId哈希得到) - 卸载时清理——移除样式标签、摘掉所有打过的属性,完全恢复原样
为什么标红不需要额外 JS
第 ④⑤ 项完全靠官方自己的标记工作:
- 当前对话 → 官方已输出
aria-selected="true" - 正在运行 → 官方已输出
data-state="ongoing"
所以插件不做任何推断,只用 CSS 选择这些既有属性。官方怎么判定,插件就怎么跟,不会出现「插件认为是 A、界面认为是 B」的错位。
目录结构
dsh-sidebar-color/
├── client.js # 浏览器半侧:OKLCH 配色引擎 + 注入 CSS + MutationObserver 打标 + 设置面板
├── index.js # 宿主半侧空实现
├── package.json # 包元数据;dsh.bundle.patch 指向 cordis.patch.yml
├── cordis.patch.yml # Loader 注册(insert id: sidebar-color)
├── install.ps1 # 一键安装(Windows)
├── install.sh # 一键安装(macOS / Linux)
└── README.md # 本文件
client.js 内部结构
| 区块 | 职责 |
|---|---|
| OKLCH 引擎 | oklabToLinear / linearToOklab / oklchToHex / hexToOklch / hueDistance / buildHues |
| 设置存储 | defaultSettings / loadSettings / saveSettings(localStorage) |
| CSS 模板 | 5 项功能的样式规则(调色板部分动态生成) |
buildPaletteCss |
按设置生成 --ws-color-N 变量与槽位绑定 |
createSettingsPanel |
纯 DOM 设置面板(不依赖 React) |
paletteIndex |
sdbm 哈希,workspaceId → 槽位 |
apply |
挂载样式、测背景色相、装配面板、MutationObserver 打标、卸载清理 |
package.json 关键字段:
{
"name": "dsh-sidebar-color",
"type": "module",
"main": "index.js",
"dsh": {
"bundle": { "patch": "./cordis.patch.yml" },
"client": { "platform": "web", "inject": [] }
}
}
变更记录
0.5.0
- 新增 OKLCH 配色引擎:6 色改为感知均匀色彩空间动态生成,深浅主题同色相、仅亮度不同
- 新增 防撞色:探测背景色相,冲突区 ±45° 整段让出,实测最小距离 67.5°
- 新增 可视化设置面板(右下角彩虹按钮):开关 5 项功能、逐槽位调色相、调亮度/饱和、恢复默认
- 新增 设置持久化到 localStorage,跨重启保留
- 新增 点击面板外部即可关闭
- 修正 README 关于热重载的错误说法(原先写"必须重启",实际改
client.js会热重载) - 修正
buildHues第一版算法:整体顺延永远无解,改为剔除冲突区后重排
0.4.0
- 新增 ⑤ 运行中的转圈圆环标红(只染
data-state="ongoing",黄点 / 绿点保持官方色) - 补全 README:安装、更新、开发流程、自定义颜色、排错指南、兼容性、实现原理
0.3.0
- 新增 ④ 当前对话标题标红
- 修复选择器:原先误用
.title(官方实际类名是hIlkoa_title,不匹配),改为结构定位> span:nth-child(2) - 修正文档中关于「面板」的错误术语
0.2.0
- 调色板改为按
workspaceId稳定哈希取色,重排 / 重启后颜色不变 - 深色主题适配
- 行底色改用
:not(:hover),让位给官方 hover / 选中高亮 - 修复拖拽 / 删除的退出动画闪白问题
许可证
MIT
No comments yet. Be the first to write one.