98 lines
15 KiB
Markdown
98 lines
15 KiB
Markdown
# 变更记录
|
||
|
||
版本说明按倒序排列。提交信息遵循 [CONTRIBUTING.md](CONTRIBUTING.md) 的单行规范,因此每次改动"为什么这样改、影响面是什么"记在这里,而不是提交信息里。
|
||
|
||
## v1.0.10
|
||
|
||
- 新增:**应用内轻弹窗的自动关闭时间可以在插件页设置**(3 / 6 / 10 / 30 秒,或**永不**)。原来固定 6 秒,现在:
|
||
- 插件页多了一组「轻弹窗」,选项就是它要设的值,选中的那一个是主色按钮样式(`role=radiogroup`,键盘可聚焦);
|
||
- 「永不」就是 `0`:卡片不再自己消失,要自己点 ✕ 或按 `Esc`。鼠标停在卡片上暂停计时的行为不变,同屏上限仍是 3 条,所以「永不」也不会越堆越多;
|
||
- 改这个值时,**屏幕上已有的卡片会按新值重新计时**(鼠标正停在上面那张除外,它要等你移开才开始计时),不会留着旧时间表继续走;
|
||
- 这个值与三个开关存在**同一份**浏览器本地记录里,各自的写入是合并式的:只存过开关的旧记录能正常升级,改开关也不会把关闭时间重置回去;取值只接受上列选项,别的值一律退回默认 6000ms。
|
||
- 调整:**「会话已完成」的提醒,描述行只显示会话题目**。标题已经写着「会话已完成」,描述再写一遍「已完成这一轮回答」只是重复;现在描述就是会话标题本身(没有标题的会话仍显示「未命名会话」)。字典里的 `body.completion` 随之删除。
|
||
- 顺带清掉两个死键:`settings.title`、`settings.kinds.label`(插件页早就改用 `config.section.*` 与 `settings.kind.*`,这两个键没有任何地方读)。现在中英各 62 个键,一一对应、没有死键。
|
||
- 测试从 44 条增加到 52 条:弹窗生命周期的 5 条(按时关闭 / 永不由时间关闭 / 悬停暂停后按新值续期 / 非法值退回默认 / 同屏上限),存储的合并与校验 3 条,插件页新选项的渲染与回写 1 条。
|
||
|
||
## v1.0.9
|
||
|
||
- 轻弹窗改成 **DSH 的浮层卡片**,跟随 DSH 的深色 / 浅色模式。原来用的是 DSH 的 `--dsw-alias-toast-bg`,而那个令牌在**两种模式下都是深灰**(浅色模式 `#353638`、深色模式 `#43454a`),所以在浅色页面里浮窗是一块接近纯黑的板子,和周围的卡片不是一种东西。现在照 DSH 自己的做法来(下面这些都是 shell 主题里真实存在、并且会随 `body[data-ds-dark-theme]` 一起切换的令牌):
|
||
- 底色 `--dsw-alias-bg-layer-2`:浅色 `#fff`、深色 `#2c2c2e`,和浮动菜单 / 弹窗用的是同一层;
|
||
- 发丝线与大阴影用 `--dsw-elevation-stroke-color` + `--dsw-elevation-prominent`(DSH 菜单的做法,发丝线取 `--dsw-alias-border-l1`:浅色 `#0000000a`、深色 `#ffffff0f`);
|
||
- 文字改 `--dsw-alias-label-primary` / `-secondary` / `-tertiary`,不再是写死的白字加 `opacity`;
|
||
- 入场动画用 shell 自己的 `--ds-transition-duration` 与 `--ds-ease-in-out`。
|
||
- 「查看」按钮改成 `--dsw-alias-state-business-primary`(浅色 `#4176e6`、深色 `#7aaaff`);原来是写死的 `--dsw-static-deepseek-400`,在白底上对比度不够、也不随主题变化。关闭按钮用 `--dsw-alias-label-tertiary`,hover 升到主文字色。三类图标仍是状态令牌:完成绿 `#22c55e`、授权琥珀 `#dd8629`、提问蓝(随主题)。
|
||
- 新增 `tests/unit/styles.test.js`(5 条)把两条不变量钉住:**样式表里不出现字面颜色、也不用 `--dsw-static-*` 这类不随主题切换的令牌**;弹窗必须用上面那套浮层配方,且**不许再出现 `--dsw-alias-toast-bg`**。以后谁把颜色写死、或又退回那个深色板子,测试会直接失败。
|
||
- 行为未改:位置(右上角)、尺寸、停留时间、hover 暂停、`Esc` / ✕ 关闭、同屏 3 条都不变,只换皮。
|
||
|
||
## v1.0.8
|
||
|
||
- 修复:**授权与提问两类提醒从来不会弹**(只有「会话已完成」会弹)。原因不是判据写错了,而是投递前的「是否还值得提醒」那道闸门用错了事实:
|
||
- `stillWorth` 原本对所有提醒都要求「会话已经不在运行」,可待处理请求恰恰出现在会话仍在运行的时候——客户端的 `running` 只镜像宿主的 `api-session/status`,和有没有待处理请求是两件独立的事(`dsh-client-ui-session` 的 `observeRunning` 就是这么写的),于是每条授权 / 提问提醒都在 400ms 确认窗口结束时被静默丢掉;
|
||
- 更糟的是丢之前 `pendingNotice` 已经记下了这个请求,所以它再也不会被重新排进队列——同一请求只报一次的规则反而变成了"一次都不报"。
|
||
- 现在两类提醒用各自该问的问题:**待处理请求问「它还在等吗」**(请求被你自己答掉就不提醒,还在就提醒,不看运行状态),**完成提醒仍问「这一轮真的停下来了吗」**(在确认窗口里又跑起来就不提醒)。
|
||
- 修复:**计划确认(`plan-review`)的文案从 v1.0.1 起就是死代码**——`copyFor` 先判断 `kind === 'question'`,而计划确认正是以 `kind: 'question'` 入队的,于是「计划正在等待你确认」永远走不到,实际显示的是提问那段文案。现在先看判别符,计划确认用自己的文案,与 README 的说明一致。
|
||
- 投递节流不再丢待处理提醒:1.5 秒的洪泛保护原本会直接吃掉被拦下的提醒,现在**待处理请求**被拦下时会回到队列、下一个 tick 重试(只有你能清掉它,所以它一直是欠你的);完成提醒保持原有的丢弃语义,多个会话同时结束仍然不会刷屏。
|
||
- 重新设计插件页(**插件 → 会话通知**):原来是一段孤立说明 + 四段标题与行标题同字号的段落,状态区把四句话和按钮挤在一行里。现在:
|
||
- 顶部一句「提醒是怎么送出去的」,下面三组:**提醒内容 / 系统通知权限 / 运行状态**,组标题加粗,组内是「左侧对象 + 右侧唯一控件」的列表,行之间用细线分隔;
|
||
- 权限状态带一个小圆点(绿=已开启,黄=未授权,红=被系统关掉,灰=当前环境不支持),下面一行按情况给出该去哪授权或该按钮验什么;
|
||
- 运行状态改成**键值对照表**(窗口状态 / 会话监听 / 最近一次投递 / 待补发提醒),最近一次投递拆成「时间 · 通道」加下一行提醒类型,不再是四个句子堆在一个格子里;
|
||
- 「测试提醒」独立成行右对齐,按钮区分主次(未授权时的「允许通知」是主按钮),行高与圆角统一。
|
||
- 字典随之增删:新增 `config.diag.watch`、`config.diag.replayValue`,`config.diag.replay` 改成短标签「待补发提醒」、`config.diag.replayNone` 改成「没有」,两个字典键集合仍然完全一致,没有死键。
|
||
- 测试从 36 条增加到 39 条:新增「待处理请求放着 `running: true` 也照样该提醒」的回归用例(这条如果早就有,v1.0.7 之前就能发现上面那个 bug)、计划确认文案用例,并把页面渲染测试改到新的结构与文案上。
|
||
|
||
## v1.0.7
|
||
|
||
- 重构:**客户端源码拆成模块,`client.js` 从「手写文件」变成「构建产物」**。原来的 `client.js` 是 1452 行单文件,通知引擎、轻弹窗、插件页、观察器、字典、样式、图标全塞在一个 `apply` 里,改任何一处都要在同一个文件里上下翻。现在:
|
||
- `src/client/core/` 是行为:`observe`(一轮派生)、`delivery`(通道决策、节流、400ms 确认窗口)、`system-channel`(系统通知与平台回执)、`replay`(回前台补发)、`toasts`(弹窗栈与计时)、`actions`(两个测试按钮、权限请求、开关)、以及 `copy` / `session` / `storage` / `store` / `log`;
|
||
- `src/client/ui/` 是界面:`ToastLayer`、`KindRow`、`ConfigSection`、`NotifyObserver`、`icons`、`styles`、`hooks`;
|
||
- `src/client/i18n/` 是字典与翻译器,`src/client/platform.js` 是浏览器与平台事实,`src/client/plugin.js` 是组合根(建 store、装配模块、注册三个 slot),`src/client/index.js` 是构建入口。
|
||
- **`client.js` 仍然是包根那一个文件,安装路径与发布清单都没变**:`exports`、`files`、`main`、`icon`、`dsh` 与 `cordis.patch.yml`、`locale/` 全部原样,使用者依旧零依赖、零构建。
|
||
- 新增 `scripts/build-client.mjs`(esbuild):把 `src/client/**` 打包成一个自包含单文件,并校验它仍然满足注册契约(只有一个 factory、`require('react')` 落在 factory 内、没有顶层 `import`/`export`、除了 `react` 不再向模块表要别的模块)。这一步无法省略:客户端模块系统只交给插件一个自包含 bundle,factory 里的 `require` 不能 require 同一个包里的相对文件。
|
||
- 新增 `tests/`(`pnpm test`,用 `node --test`,无第三方依赖):26 个纯函数单测(文案、会话派生、存储、字典与翻译器)、4 个产物测试(注册 id、factory 返回值、`apply` 在没有 DOM 的 Node 里也能跑通、**产物与 `src/**` 是否一致**)、6 个渲染测试(用一份最小 React 替身渲染插件页与轻弹窗,验证重构后的 props 装配:开关的选中态、诊断行、按钮回调、观察器的健康上报)。以后改完源码忘了重新构建,测试会直接失败。
|
||
- 维护者现在需要跑一次 `pnpm install`(唯一 devDependency 是 esbuild);**使用者不需要**。README 的安装说明按这个区分改写了,并新增「仓库结构」一节。
|
||
- 行为未改:三类提醒的判定、通道选择、节流与确认窗口、补发与去重、开关的存储键、CSS 全文与 `dsn-*` 类名、全部字典键与文案都逐字保持(构建产物与 v1.0.6 的字符串逐条比对通过,样式表 4615 字节完全一致)。
|
||
- 顺带记录一个**本次没有修的既有缺陷**:`body.planReview`(「计划正在等待你确认」)在 v1.0.6 里已是死代码——`copyFor` 先判断 `kind === 'question'`,而计划确认正是以 `kind: 'question'` 入队的,所以计划提醒实际显示的是提问那段文案。修它要调整判断顺序、属于行为变更,因此这次只把现状写进 `src/client/core/copy.js` 的注释,并在 `tests/unit/copy.test.js` 里钉住当前输出。
|
||
|
||
## v1.0.6
|
||
|
||
- 修复:**窗口不在前台时,提醒有可能一次都看不到**。排查证据:一次真实投递(会话 17:52:29 结束)在插件页留下 `09:52:30 · 系统通知`——`09:52:30` 是 UTC,本机时间是 17:52:30;而 Windows 的通知平台记录 `LastNotificationAddedTime` 停在 70 分钟前。也就是说 `new Notification()` 没抛错,但**构造函数成功不等于通知真的弹出来了**,加上系统通知的气泡只存在几秒,人不在电脑前时它等于没送达。这一版不再把"发出去"当成"收到了":
|
||
- 每条系统通知都订阅 `show` / `error`:系统是否确认显示会写进插件页的「最近一次投递」,不再只报"系统通知"三个字;
|
||
- **凡是在窗口不在前台时投递的提醒,都会在窗口回到前台的那一刻用应用内轻弹窗补发一次**。同一会话同一类只保留最新一条,超过 30 分钟不再补发;"正在看的会话不打扰"这条规则不适用于补发,因为它发生的时候你并不在看。唯一的例外是系统确认气泡已弹出、且你在 20 秒内就回到窗口(气泡还在屏幕上,不再重复);
|
||
- 点掉系统通知本身(`click`)会取消对应的补发,不重复打扰。
|
||
- 修复「最近一次投递」的时间显示成 UTC(比本地时间早 8 小时,17:52 显示成 09:52)的问题,现在显示本机时间。
|
||
- 修复确认窗口的队列会把提醒永久卡住的问题:一次确认窗口只投递一条,剩下没轮到的会自己再排一次(以前排完之后队列里再没人触发,后面的提醒就被吞了)。
|
||
- 系统通知对象改为有界持有引用:防御性改动,避免显示还没落定时对象被回收(实测中保留引用与否都能送达,所以这不是那次丢失的原因)。
|
||
- 插件页「运行状态」新增一行:还有几条提醒在等你回到窗口时补发。
|
||
|
||
## v1.0.5
|
||
|
||
- 修复:**应用在后台时不发系统通知**。前台/后台以前只靠 `window` 的 `focus`/`blur` 事件记住,桌面外壳里 `blur` 可能不到,插件就一直以为窗口在前台,于是走了轻弹窗分支(而用户没在看,表现就是完全没有通知)。现在每次投递都现读 `document.visibilityState` 与 `document.hasFocus()`,任一表示不可见即走系统通知;观察器订阅的事件只是让重算更及时,不再决定通道。
|
||
- 系统通知构造失败时降级:改用轻弹窗,并把被拒原因写进插件页,不再静默失败。
|
||
- 插件页新增诊断:窗口当前状态(前台/后台,即会走哪条通道)、观察器健康、最近一次投递的通道与时间;「测试系统通知」按钮直接走系统通道(前台也照发),用来单独验证系统通知是否可用。
|
||
- 修掉日志前缀重复(`session-notify: session-notify:`)。
|
||
|
||
## v1.0.4
|
||
|
||
- 配置块去掉重复:插件页顶部已经有 DSH 渲染的插件标题与描述,原配置块又写了一遍标题和几乎一样的说明。现在这一段直接用一句「提醒是怎么送出去的」开头,随后进入设置项。
|
||
- 移除未使用的字典键 `config.title` / `config.note`,保证字典里没有死键。
|
||
|
||
## v1.0.3
|
||
|
||
- 设置从「设置 → 通用」移到插件自己的介绍页:注册 `plugins.bundle.config`(key 取包名),与官方 `dsh-experimental-voice-input-bundle` 用的是同一个口子;通用设置里不再有本插件的行。
|
||
- 应用内轻弹窗改成标题 + 描述两行:标题是提醒类型(会话已完成 / 需要授权 / 需要回答),描述是会话题目与细节;关闭按钮从 18px 放大到 28px 的方形热区,「查看」改成有 hover 背景的文字按钮,整条浮窗 hover 时暂停自动消失。
|
||
- 三个开关改为存浏览器本地(`localStorage`),重开页面、重装插件都保留;仍然不写 DSH 的配置文件。
|
||
- 插件页配置分四段:说明、提醒内容(三个开关)、系统通知权限、运行状态。
|
||
|
||
## v1.0.2
|
||
|
||
- 补上 `ctx.locale.register('session-notify', { zh, en })`:没有注册时 `locale.bind(ns)` 会把 key 原样返回,界面上就显示成 `settings.title` 这样的原始键。
|
||
- 字典兜底与 locale 兜底同时保留:缺框架的 `t`、或 locale 服务没保存注册,都不会显示原始键。
|
||
- 快照语言字段改为真实字段 `snapshot.active`。
|
||
|
||
## v1.0.1
|
||
|
||
- 首个发布版本:会话完成 / 需要授权 / 需要回答三类提醒。
|
||
- 窗口不在前台走系统通知(Windows / macOS / Linux 同一条渲染进程通道,无平台分支);窗口在前台走应用内轻弹窗;正在看的那个会话完成时不打扰。
|
||
- 只对「运行中 → 空闲」的转变提醒,同一会话同一轮只报一次,同一待处理请求只报一次;子智能体会话与空白会话跳过;多个会话同时完成有 1.5 秒节流,完成提醒前有 400ms 确认窗口。
|
||
- 修复:无渲染观察器原先挂在 `sidebar.panellist`,而该 slot 的宿主会把每个条目的 id 当作一个左侧面板按钮,导致左侧多出一行空面板并挤坏侧边栏;现改挂通用浮层 `shell.overlay`。
|