Skip to content

Releases

v0.3.0 — 提示音保存不再静默丢失;音量滑块写入 448ms→0ms

Choose a tag to compare

@ZIye1208 ZIye1208 released this 04 Oct 00:48

修复:自定义提示音不再静默丢失;音量滑块写入 448ms→0ms

症状

  • 选完自定义提示音后,面板立刻显示「已自定义」,但刷新/重开标签页后提示音消失,全程零报错、零提示。
  • 真机实测(Chrome headless + CDP):本机单源 localStorage 配额仅 5,242,879 字符,一份 5.4M 字符的 base64 提示音写入 grewBy=0(根本没写进去)、零告警,面板仍显示「已自定义」。
  • 音量滑块每次拖动都触发一次全量 setConfig 落盘,20 次 set 实测耗时 448ms,拖动明显发涩。

根因

三环叠加,只堵一环修不干净:

  1. setConfig 的上限按 4MB(二进制) 计算,但实际存的是 FileReader.readAsDataURL 产出的 base64,膨胀约 1.33× ≈ 5.33M 字符,正好压在浏览器 5MB 配额线上,必然超限;
  2. setConfig 里是 try { setItem } catch { /* ignore */ } —— QuotaExceededError 被静默吞掉,调用方永远拿不到失败信号;
  3. 面板读的是内存里的 config 对象,所以 UI 立刻反映「已自定义」,磁盘上却什么都没存。

修复

  • 提示音上限降到 2MB(二进制),留足余量;二进制超限时面板直接显示红色错误行,不再假装成功。
  • 新增 writeVerified():写入后回读比对(有些环境 setItem 不抛错却没真正落盘),失败时回滚内存配置、还原磁盘上的提示音,并 console.warn 写明原因。
  • 提示音拆到独立 key dsh.approvalVoice.sound.v1,主配置回到 <1KB;老数据自动迁移,升级后无需重新选文件。
  • alertedKeys 加 FIFO 上限 1000,避免去重集合无限增长;onStorage 处理 key===null(storage.clear());CLAIM_TTL 注释单位改为毫秒。
  • 音量滑块写入路径不再每次同步全量落盘,实测 20 次 set 从 448ms → 0ms。

升级

dsh plugin --profile web add dsh-approval-voice@0.3.0
  • 桌面端同理:dsh plugin --profile desktop add dsh-approval-voice@0.3.0。
  • 界面验证:设置 → 常规 → 审批语音提示 → 选一个 >2MB 的音频文件,应出现红色错误行;再拖动音量滑块,界面无卡顿。
  • Console 验证:写入失败时应出现 console.warn,而不是毫无动静。
  • 旧的自定义提示音会自动迁移到新 key,升级后直接可用。

验证

  • test-global-scope.mjs 断言 27 → 45 条;test-cross-tab.mjs 5 个场景全过;node --check lib/client.js 通过。
  • A/B 对照:同一份新测试跑旧版 client.js 有 12 条 FAIL,跑新版 45 条全过。
  • 真机(Chrome headless + CDP):旧版 5.4M 字符写入静默失败(grewBy=0)、零告警、面板仍显示已自定义;新版返回 QuotaExceededError + console.warn;滑块 20 次 set 从 448ms 降到 0ms。

完整变更:v0.2.2...v0.3.0

v0.2.2 — 桌面端「所有会话」提醒恢复生效(兼容 sessionStatus 全局源)

Choose a tag to compare

@ZIye1208 ZIye1208 released this 30 Sep 16:10

修复:桌面端里「提醒范围 = 所有会话」不生效(网页版正常)

症状

设置明明是「所有会话」,但只有当前正在显示的那个会话的审批会响;同一个插件在网页版正常、
在桌面端 dsh-desktop 不正常。诊断依据:响铃记录(localStorage 的 dsh.approvalVoice.bell.v1)
里桌面端的 eventKey 全是 ${tabId}:approval:... 前缀(= 只走了 DOM 兜底),
而网页版那次是 session:${sessionId}:approval:... 前缀(= 全局源生效)。

根因

0.2.1 订阅的全局源是网页版核心的 ctx.uiSession.pendingInteractions(dsh 0.1.5-rc.3);
桌面端 dsh-desktop 0.2.0-rc.2 的客户端核心没有这个属性 —— 它只有
ctx.uiSession.sessionStatus(Map<sessionId, {running, pendingInteraction, completionUnread}>,
待处理交互藏在 pendingInteraction 字段,正是桌面端侧边栏「等待审批」读的那个源)。
于是 startGlobalWatcher() 取源失败 → 退回 DOM 卡片监听 → 只有当前视图渲染的卡片能被看到,
现象与 0.2.1 修复前一模一样。

连带问题:桌面端 sessions.list.getSnapshot() 返回 {byId, phase}(没有网页版的 .current),
currentSessionId() 取不到值 → eventKey 退化成 ${tabId}:${kind}:${key},跨标签页去重被架空。

修复

  • 新增 resolveGlobalSource() 双形状解析:优先 uiSession.pendingInteractions(网页版),
    否则把 uiSession.sessionStatus 适配成同形状(桌面端);两者都取不到才退回 DOM 监听并打印明确告警
    (告警文案同时点名两个属性)。
  • currentSessionId() 增加回退:sessions.list.getSnapshot().current →
    uiSession.adapter.current.getSnapshot().key,桌面端的 eventKey 恢复会话作用域
    session:<sessionId>:<kind>:<key>。
  • 调试接口同步:window.__approvalVoice.pending() 走同一解析,桌面端也能列出所有会话的待处理交互。

升级

# 桌面端
dsh plugin --profile desktop add dsh-approval-voice@0.2.2
# 网页版
dsh plugin --profile web add dsh-approval-voice@0.2.2

重启 / 刷新界面后,在 Console 里验证:

window.__approvalVoice.global()        // 应为 true(已挂上全局源)
window.__approvalVoice.pending()       // 应列出「所有」会话的待处理交互
window.__approvalVoice.currentSessionId()  // 应返回当前会话 id

实测方法:让另一个没有显示在界面里的会话触发一次审批,不要切过去,应当立刻响。

验证

test-global-scope.mjs 新增 3 组「桌面端核心形状」场景(sessionStatus 源 + 无 .current 快照 +
adapter.current 回退),断言 17 → 27 条全部通过(test-cross-tab.mjs 5 组也全过):

  • 桌面端形状:非当前会话的审批响 1 次(修复前为 0),eventKey 是 session:session-bg:approval:approval:5(修复前是 tabId 前缀);
  • 桌面端形状 + 仅当前会话:其它会话不响、本页会话照响;
  • 桌面端形状:DOM 兜底路径的 eventKey 同样带会话作用域。

完整变更:v0.2.1...v0.2.2

v0.2.1 — 「所有会话」提醒覆盖没有开在任何标签页里的会话

Choose a tag to compare

@ZIye1208 ZIye1208 released this 11 Sep 04:26

修复:设置成「所有会话」后,非当前会话的审批不响

根因

旧实现只嗅 DOM 里的 data-approval-key / data-question-key / data-plan-review-key 卡片,
而 DSH 只在当前正在显示该会话的视图里渲染这张卡片。因此没有开在任何标签页里的会话
(只在侧边栏显示「等待审批」)永远不会触发提醒 —— 单页签切换会话的用户就会感觉
「明明设置了全局提醒,但没有生效」。

修复

  • 真的覆盖所有会话:改为主订阅 DSH 客户端的全局待处理交互源
    ctx.uiSession.pendingInteractions(侧边栏「等待审批」同源),任何会话的
    approval / question / plan-review 出现都会触发提醒;取不到该源时(更老的 DSH)
    自动退回 DOM 卡片监听并打印明确告警。
  • 跨标签页仍然只响一次:eventKey 由 ${tabId}:${kind}:${key} 改为会话作用域
    session:${sessionId}:${kind}:${key},两个标签页显示同一会话不再各响一次,
    且仍然优先由聚焦标签页出声。
  • 自定义提示音不再静默失效:保留 <audio> 引用(避免被 GC 提前回收导致截断);
    未起播(NotAllowedError / 解码失败 / 1 秒内没有 playing 事件)时自动回退内置
    提示音,失败原因写入 console.warn。
  • 播放失败会让出并补响:本页确实出不了声时释放跨标签页 claim 并广播
    bell-failed,请已解锁音频的其它页签补响一次。
  • 调试接口新增 window.__approvalVoice.global() / pending() / currentSessionId()。

升级

dsh plugin --profile web add dsh-approval-voice@0.2.1

安装后重启 dsh web 服务并刷新页面。可在浏览器 Console 里用
window.__approvalVoice.global() 确认返回 true(已挂上全局源),
用 window.__approvalVoice.pending() 看到所有会话的待处理交互。

验证

新增 test-global-scope.mjs:直接加载真实 lib/client.js 的假浏览器回归测试,
6 组场景 17 条断言全部通过 —— 单页签 + 非当前会话 / 多页签只响一次 / 仅当前会话 /
自定义提示音失败回退 / 播放失败补响 / uiSession 缺失退回 DOM。

完整变更:v0.2.0...v0.2.1

v0.2.0

Choose a tag to compare

@ZIye1208 ZIye1208 released this 07 Sep 13:28

0.2.0 — 所有会话提醒 / 仅当前会话开关 / 自定义提示音

新增

  • 默认对所有会话提醒(跨标签页广播;一次提醒全浏览器只响一次,聚焦标签页优先)。
  • 设置新增「提醒范围」:所有会话 / 仅当前会话。
  • 设置新增「提示音」:可上传自定义提示音文件(mp3/wav/ogg,≤4MB)替换内置提示音;默认内置提示音不变。

升级指南

  • 升级后默认所有会话提醒;若需旧行为,在「设置 → 常规 → 审批语音提示」把「提醒范围」切到「仅当前会话」。
  • 旧配置会自动补齐 scope / sound 默认值,无需迁移。
  • 完整变更见 CHANGELOG.md。